Topic: Dynamic initialization


Author: "Garry Lancaster" <glancaster@ntlworld.com>
Date: Thu, 20 Jun 2002 17:27:41 GMT
Raw View
> > David Abrahams:
> > > I've always taken 3.6.2 paragraph 3 (appended below) to
> > > mean that you can't count on the initialization of a global
> > > object to execute unless something explicitly uses the
> > > translation unit where it's defined.

Garry Lancaster:
> > To me it seems to be giving licence to delay initialization,
> > not to avoid it completely. 3.7.1p2 seems to indicate that
> > avoidance is not permitted (except under "as-if"):
> >
> > "If an object of static storage duration has initialization or
> > a destructor with side effects, it shall not be eliminated
> > even if it appears to be unused, except that a class object
> > or its copy may be eliminated as specified in 12.8."

David Abrahams:
> Well, OK, I suppose it can run after main() exits.

Or at any time before. 3.6.2p3 permits delay but does
not mandate it.

[snip]

> > > However, I have some doubts about the phrase
> > > "...before the first use of any function
>                                                         ^^^^^^^^^^^^
> > > or object defined in the same translation unit..."

> > > What about objects like inline functions and template
                                                                xxxxxxxxxx

> > > instantiations?

> > While an inline function isn't an object it may *contain* a static
> > object. Is that what you meant?

> No, I meant "function".

(You underlined a previous use of the word "function", not
the use I was commenting upon. I have underlined the
relevant most-recent usage with xxxxxxxxx.)

Put it another way: I agree a function can affect the timing
of initialization just as an object can, but I don't agree that
a function *is* an object, which is what you claimed in the
sentence I was commenting on.

[snip]

> > Once the program is fixed, the answer to your question
> > is: yes, because of 3.7.1p2. If File 1 was in a library the
> > answer might (should?) be no though.
>
> Where does the standard ever mention different semantics for libraries?

Nowhere as far as I know. The behaviour of libraries
is of only practical interest.

Kind regards

Garry Lancaster
Codemill Ltd
Visit our web site at http://www.codemill.net

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "David Abrahams" <david.abrahams@rcn.com>
Date: Sat, 15 Jun 2002 16:27:18 GMT
Raw View
"Garry Lancaster" <glancaster@ntlworld.com> wrote in message
news:30sO8.14903$gm5.2624919@news11-gui.server.ntli.net...
> David Abrahams:
> > I've always taken 3.6.2 paragraph 3 (appended below) to
> > mean that you can't count on the initialization of a global
> > object to execute unless something explicitly uses the
> > translation unit where it's defined.
>
> To me it seems to be giving licence to delay initialization,
> not to avoid it completely. 3.7.1p2 seems to indicate that
> avoidance is not permitted (except under "as-if"):
>
> "If an object of static storage duration has initialization or
> a destructor with side effects, it shall not be eliminated
> even if it appears to be unused, except that a class object
> or its copy may be eliminated as specified in 12.8."

Well, OK, I suppose it can run after main() exits.

> (12.9 refers to elision of copies: it isn't relevant here.)

Nor is 12.8...

> > This clause is what's typically used by implementations to
> > allow them to avoid executing initializers for cout, cin, etc.
> > in translation units which #include <iostream> but which
> > aren't otherwise used.
>
> Are you sure about that? I don't think they need to find a
> rule to let them do what they want. They're implementors
> after all: they can break all the rules anyway with respect
> to how the standard header files and the things in them
> work as long as every program's observable behaviour is
> correct.

You're right. Of course it's much more convenient for them if their compiler
writer doesn't have to put in special behavior to support the library
implementation.

> > However, I have some doubts about the phrase "...before the first use of
> > any function
    ^^^^^^^^^^^^
> > or object defined in the same translation unit..."
> >
> > What about objects like inline functions and template instantiations?
>
> While an inline function isn't an object it may *contain* a static
> object. Is that what you meant?

No, I meant "function". A single inline function is potentially defined in
multiple TUs. If I stick one in a header file included by all my TUs, but
call it from only one TU, does that put an upper bound on how late dynamic
initialization may occur for any all objects?

> > Suppose I write:
> >
> > // --- File 1 ---
> > #include <cstdio>
> > template <class T> struct foo { static int const x=0; };
> > struct X
> > {
> >     X() { std::printf("initialized\n"); }
> > };
> > X x;
> >
> > // --- File 2 ---
> > template <class T> struct foo { static int const x=0; };
> > int main(
> > {
> >     return &foo<int>::x != 0;
> > }
> >
> > Does this program print "initialized\n"?
>
> I think this program is actually illegal according to 9.4.2p4
> since there is no definition of x (the static int const x = 0 lines
> are legal declarations, but you need a definition too). Maybe
> that rule doesn't apply to templates but I couldn't find any
> evidence for that.

It applies, at least if you ever need the address. That was just an
oversight.

>
> Once the program is fixed, the answer to your question
> is: yes, because of 3.7.1p2. If File 1 was in a library the
> answer might (should?) be no though.

Where does the standard ever mention different semantics for libraries?

-Dave



---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "Fernando Cacciola" <fcacciola@gosierra.com>
Date: Fri, 14 Jun 2002 18:45:22 GMT
Raw View
"David Abrahams" <david.abrahams@rcn.com> wrote in message
news:228601c20ee9$83380290$6601a8c0@boostconsulting.com...
> I've always taken 3.6.2 paragraph 3 (appended below) to mean that you
can't
> count on the initialization of a global object to execute unless someth=
ing
> explicitly uses the translation unit where it's defined. This clause is
> what's typically used by implementations to allow them to avoid executi=
ng
> initializers for cout, cin, etc. in translation units which #include
> <iostream> but which aren't otherwise used.
>
> However, I have some doubts about the phrase "...before the first use o=
f
> any function
> or object defined in the same translation unit..."
>
> What about objects like inline functions and template instantiations?
>
> Suppose I write:
>
> // --- File 1 ---
> #include <cstdio>
> template <class T> struct foo { static int const x=3D0; };
> struct X
> {
>     X() { std::printf("initialized\n"); }
> };
> X x;
>
> // --- File 2 ---
> template <class T> struct foo { static int const x=3D0; };
> int main()
> {
>     return &foo<int>::x !=3D 0;
> }
>
> Does this program print "initialized\n"?
>
We've been discussing this same issue recently on the Borland forum.
I've searched previous discussions on this on USENET and it doesn't seem =
to
be agreement on this.

Besides 3.6.2/3, its also relevant:

--------------
3.7.1 Static storage duration
2 If an object of static storage duration has initialization or a destruc=
tor
with side effects, it shall not be elimi=ADnated even if it appears to be
unused, except that a class object or its
copy may be eliminated as specified in 12.8
--------------

I think that as long as the ctor/dtor of the global object has side effec=
ts,
it will be dynamically initialized, sooner or later.

I recall that someone argued that 3.6.2/3 could imply that the dynamic
initialization could take place as late as upon program termination, afte=
r
main entered and leaved. But it still must occur, so the program should
print "initialized", but probably, after main() returned.

I also recall that it was argued this rules could only apply to static
libraries (and the executable itself), global objects inside dynamically
loaded libraries might be uninitialized (unless the dynamic library is
linked to statically).

It was also argued that this rules only applies to program translation. T=
he
linker could still decide to discard the initialization code if it isn't
referenced.
This shouldn't occur in practice, IMO, since I expect the compiler to
arrange the startup code such that these initializations (the ones with s=
ide
effects) are always referenced and therefore not discarded by the linker,
even in the pathological case of a TU containing only the global object
instance.

HTH,


--
Fernando Cacciola
Sierra s.r.l.
fcacciola@gosierra.com
www.gosierra.com








---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "Garry Lancaster" <glancaster@ntlworld.com>
Date: Sat, 15 Jun 2002 06:22:11 GMT
Raw View
David Abrahams:
> I've always taken 3.6.2 paragraph 3 (appended below) to
> mean that you can't count on the initialization of a global
> object to execute unless something explicitly uses the
> translation unit where it's defined.

To me it seems to be giving licence to delay initialization,
not to avoid it completely. 3.7.1p2 seems to indicate that
avoidance is not permitted (except under "as-if"):

"If an object of static storage duration has initialization or
a destructor with side effects, it shall not be eliminated
even if it appears to be unused, except that a class object
or its copy may be eliminated as specified in 12.8."

(12.9 refers to elision of copies: it isn't relevant here.)

> This clause is what's typically used by implementations to
> allow them to avoid executing initializers for cout, cin, etc.
> in translation units which #include <iostream> but which
> aren't otherwise used.

Are you sure about that? I don't think they need to find a
rule to let them do what they want. They're implementors
after all: they can break all the rules anyway with respect
to how the standard header files and the things in them
work as long as every program's observable behaviour is
correct.

> However, I have some doubts about the phrase "...before the first use of
> any function
> or object defined in the same translation unit..."
>
> What about objects like inline functions and template instantiations?

While an inline function isn't an object it may *contain* a static
object. Is that what you meant?

> Suppose I write:
>
> // --- File 1 ---
> #include <cstdio>
> template <class T> struct foo { static int const x=0; };
> struct X
> {
>     X() { std::printf("initialized\n"); }
> };
> X x;
>
> // --- File 2 ---
> template <class T> struct foo { static int const x=0; };
> int main()
> {
>     return &foo<int>::x != 0;
> }
>
> Does this program print "initialized\n"?

I think this program is actually illegal according to 9.4.2p4
since there is no definition of x (the static int const x = 0 lines
are legal declarations, but you need a definition too). Maybe
that rule doesn't apply to templates but I couldn't find any
evidence for that.

Once the program is fixed, the answer to your question
is: yes, because of 3.7.1p2. If File 1 was in a library the
answer might (should?) be no though.

Hope this helps.

Kind regards

Garry Lancaster
Codemill Ltd
Visit our web site at http://www.codemill.net

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "David Abrahams" <david.abrahams@rcn.com>
Date: Sun, 9 Jun 2002 02:57:32 GMT
Raw View
I've always taken 3.6.2 paragraph 3 (appended below) to mean that you can't
count on the initialization of a global object to execute unless something
explicitly uses the translation unit where it's defined. This clause is
what's typically used by implementations to allow them to avoid executing
initializers for cout, cin, etc. in translation units which #include
<iostream> but which aren't otherwise used.

However, I have some doubts about the phrase "...before the first use of
any function
or object defined in the same translation unit..."

What about objects like inline functions and template instantiations?

Suppose I write:

// --- File 1 ---
#include <cstdio>
template <class T> struct foo { static int const x=0; };
struct X
{
    X() { std::printf("initialized\n"); }
};
X x;

// --- File 2 ---
template <class T> struct foo { static int const x=0; };
int main()
{
    return &foo<int>::x != 0;
}

Does this program print "initialized\n"?

------

3 It is implementation-defined whether or not the dynamic
initialization (8.5, 9.4, 12.1, 12.6.1) of an object of namespace
scope is done before the first statement of main. If the
initialization is deferred to some point in time after the first
statement of main, it shall occur before the first use of any function
or object defined in the same translation unit as the object to be
initialized. 31) [Example:

// -- File 1 --
#include "a.h"
#include "b.h"
B b;
A::A(){
  b.Use();
}

// -- File 2 --
#include "a.h"
A a;

// -- File 3 --
#include "a.h"
#include "b.h"
extern A a;
extern B b;
int main() {
  a.Use();
  b.Use();
}

It is implementation-defined whether either a or b is initialized
before main is entered or whether the initializations are delayed
until a is first used in main. In particular, if a is initialized
before main is entered, it is not guaranteed that b will be
initialized before it is used by the initialization of a, that is,
before A::A is called. If, however, a is initialized at some point
after the first statement of main, b will be initialized prior to its
use in A::A. ]

+---------------------------------------------------------------+
                  David Abrahams
      C++ Booster (http://www.boost.org)               O__  ==
      Pythonista (http://www.python.org)              c/ /'_ ==
  resume: http://users.rcn.com/abrahams/resume.html  (*) \(*) ==
          email: david.abrahams@rcn.com
+---------------------------------------------------------------+

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]