Topic: Clarification on order of initialization


Author: mat@mole-end.matawan.nj.us
Date: Mon, 16 Aug 1993 01:28:59 GMT
Raw View
In article <CBpAns.2At@sugar.NeoSoft.COM>, daniels@NeoSoft.com (Brad Daniels) writes:
> I have run into a problem with the order of initialization across
> compilation units.  ...

 ...
> #include <String.h>
>
> const String EnvFile(const String ename, const String name);
>
> extern const String dbfilename = EnvFile("DBFILENAME","dbfile");
>
> ---
>
> In the above example, the initializer for dbfilename in b.C has to happen
> after the initializaer for dir in a.C.
>
> The standard working document and Stroustrup's 2nd ed. (I still don't have the
> ARM, sigh.) both say (std section 3-4, Stroustrup p. 485):
>
> "The initialization of nonlocal static objects in a translation unit is
> done before the first use of any function or object defined in that trans-
> lation unit.  ...

> Several people have told me that the ARM explicitly says that there is
> no order imposed on the initialization across different translation units.
> Were they misinterpreting the above, am I misinterpreting the above, or
> is there additional text in the ARM which states that there is no ordering?

You have missed the point of the word `defined'.  EnvFile is _defined_ in
b.C, but dbfilename is only _declared_ in it (and vice-versa in a.C).
Since they are not defined in the same file, there is no relative order
imposed upon their initializations.
--
 (This man's opinions are his own.)
 From mole-end    Mark Terribile

 mat@mole-end.matawan.nj.us, Somewhere in Matawan, NJ




Author: daniels@NeoSoft.com (Brad Daniels)
Date: Fri, 13 Aug 1993 13:54:46 GMT
Raw View
I have run into a problem with the order of initialization across
compilation units.  Here's my particular situation (just writing on the
fly, there may be errors...):

file a.C:
#include <stdlib.h>
#include <String.h>

const String Env(const String v, const String def)
{
    const char *r = getenv(v);
    if (r == NULL) return def;
    return r;
}

static const String dir = Env("DIRNAME",".");

const String EnvFile(const String ename, const String name)
{
    const char *r = getenv(ename);
    if (r != NULL) return r;
    return ename + "/" + name;
}

file b.C:
#include <String.h>

const String EnvFile(const String ename, const String name);

extern const String dbfilename = EnvFile("DBFILENAME","dbfile");

---

In the above example, the initializer for dbfilename in b.C has to happen
after the initializaer for dir in a.C.

The standard working document and Stroustrup's 2nd ed. (I still don't have the
ARM, sigh.) both say (std section 3-4, Stroustrup p. 485):

"The initialization of nonlocal static objects in a translation unit is
done before the first use of any function or object defined in that trans-
lation unit.  Such initiaizations may be done before the first statement
of main() or deferred to any point in time before the first use of a function
or object defined in that translation unit.  ... No further order is imposed
on the initialization of objects from different translation units..."

Several people have told me that the ARM explicitly says that there is
no order imposed on the initialization across different translation units.
Were they misinterpreting the above, am I misinterpreting the above, or
is there additional text in the ARM which states that there is no ordering?

It seems to me that in the context of my example, the initializer for
dbfilname uses a function in a.C, and that the initializers for any
variables in a.C must therefore happen before entering EnvFile in order
for the implementation to be standard conforming.  The text quoted above
says that no *further* order is imposed, not that no order at all is
imposed.  Note that my example points out a further problem, in that
the "dir" variable is local, and the standard doesn't address when such
variables should be initialized in cases of cross-compilation unit
dependencies, but if you make "dir" extern, the example conforms to the
standard's text exactly, and still has the problem.

The fact that Cfront doesn't seem to even try to get this right, and neither
does any other compiler I know of, implies that I may be taking a stronger
interpretation of the above text than others have.  Also, neither document
addresses the issue of initialization dependency cycles (e.g. object A
im module a.C requires object B in module b.C which in turn requires
object C in module a.C, thus creating a cycle in terms of the above text,
though not in terms of actual data dependencies.)

Am I reading the intent correctly?  If not, shouldn't it work the way I
describe?  A programmer should not have to worry about constants defined
in libraries, and with the current state of affairs, such constants can
be trouble.  You can also get into all kinds of trouble with static data
members used in default constructors this way.

Actually, the text in question should probably be made more specific.
Rather than initialization being done before the first use of any function
or object defined in the translation unit, the initialization of any static
object (local or nonlocal) should be required to be performed before the
first use of any object or function in the translation unit which in turn
uses that object.  In this way, module cycles which are not data dependency
cycles (as discussed above) would be allowed.  Even if this change is con-
sidered too much of a pain to implement (since it would involve some messy
data dependecy graph work), the text quoted above should at least be changed
to include similar requiremnts for local static objects.

I'm really going to have to find out how to make a formal proposal.  Why
isn't there an FAQ discussing how to make proposals to the committee?
If anyone can spare the time to give me a pointer, I'd much appreciate
it.

- Brad
--
Brad Daniels   |  "Let others praise ancient times.
daniels@neosoft.com  |   I am glad I was born in these."
I don't work for NeoSoft, and | - Ovid (43 B.C. - 17 A.D)
don't speak for my employer. |