Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Initialization of Static Objects

0 views
Skip to first unread message

Thomas Kemmer

unread,
Jul 20, 2005, 10:09:53 AM7/20/05
to
Hello everybody,

I got a little confused lately about the initialization of static
(global, namespace-scope) objects.

Stroustrup's TC++PL §10.4.9 states that

A variable defined outside any functions (that is, global, namespace
and class static variables) is initialized (constructed) before
main() is invoked [...] Dynamic linking complicates this picture
slightly by delaying the initialization until the code is linked
into the running program.

This is how I always thought it worked: static objects are constructed
before main() is invoked (in whatever order); objects in dynamic
libraries are initialized when the system's linker/loader decides it's
time to do so, e.g. after calling your system's version of dlopen().
Quite (maybe too?) simple, really ;-)

But my (somewhat dated, I admit) 1998 edition of the ISO C++ Standard
says in §3.6.2 (3)

It is implementation-defined whether or not the dynamic
initialization [...] 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.

Are there any implementations that defer intialization of static
objects in such a way (leaving dynamic libraries aside)? If yes, are
there any issues that one should be aware of?

For example, I know that intialization of _function-static_ objects
may not be thread-safe; provided I do not start any threads before
main() is called, I always thought that with global objects I don't
have this particular problem, since they will have been properly
constructed.

Kind regards,

- Thomas

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

ka...@gabi-soft.fr

unread,
Jul 21, 2005, 11:52:58 AM7/21/05
to
Thomas Kemmer wrote:

> I got a little confused lately about the initialization of
> static (global, namespace-scope) objects.

> Stroustrup's TC++PL §10.4.9 states that

> A variable defined outside any functions (that is, global,
> namespace and class static variables) is initialized
> (constructed) before main() is invoked [...] Dynamic linking
> complicates this picture slightly by delaying the
> initialization until the code is linked into the running
> program.

> This is how I always thought it worked: static objects are
> constructed before main() is invoked (in whatever order);

That's how it works in reality. There are, in fact, enough
idioms that depend on it that no compile would dare break.

> objects in dynamic libraries are initialized when the system's
> linker/loader decides it's time to do so, e.g. after calling
> your system's version of dlopen().

A little less certain -- in the past, there have been
implementations which never called the constructors for static
objects in a dynamic library. But for any reasonably recent
version of a C++ compiler (say, in the last seven or eight
years), yes.

> Quite (maybe too?) simple, really ;-)

> But my (somewhat dated, I admit) 1998 edition of the ISO C++
> Standard says in §3.6.2 (3)

> It is implementation-defined whether or not the dynamic
> initialization [...] 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.

Note that the alternative is not implementable in practice.

> Are there any implementations that defer intialization of
> static objects in such a way (leaving dynamic libraries
> aside)?

No. And there never will be; too many programs count on
initialization before main.

I think that the alternative was added expressedly to allow
dynamic loading. More or less. Now that the committee is
addressing dynamic loading (maybe), we might be able to clean up
and simplify the specification, and just require before main.

> If yes, are there any issues that one should be aware of?

In theory, or in practice? In practice, I just ignore the
possibility.

> For example, I know that intialization of _function-static_
> objects may not be thread-safe; provided I do not start any
> threads before main() is called, I always thought that with
> global objects I don't have this particular problem, since
> they will have been properly constructed.

Quite. There's also a number of idioms which count on static
objects enrolling themselves before main is entered. No
compiler would dare break these, so you're probably safe in
ignoring the issue, and just supposing "before main".

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Andreas Huber

unread,
Jul 22, 2005, 7:18:19 AM7/22/05
to
> > It is implementation-defined whether or not the dynamic
> > initialization [...] 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.
>
> Note that the alternative is not implementable in practice.

Why not?

> > Are there any implementations that defer intialization of
> > static objects in such a way (leaving dynamic libraries
> > aside)?
>
> No. And there never will be; too many programs count on
> initialization before main.

It is worth noting that there is at least one popular compiler (MSVC)
that strips unreferenced static variables from *lib* files. Without
precautions (disable stripping) static objects in such lib files can
therefore not be used for registration schemes (where typically no code
ever references the static variable).
This is only the case if cpps are first compiled into lib files and
then linked into the exe. If all .cpps are directly compiled into the
exe then all statics are initialized before main().

This behavior can be interpreted as deferred initialization, because
the static is *never* accessed.

Regards,

--
Andreas Huber

When replying by private email, please remove the words spam and trap
from the address shown in the header.

ka...@gabi-soft.fr

unread,
Jul 25, 2005, 7:39:00 AM7/25/05
to
Andreas Huber wrote:
> > > It is implementation-defined whether or not the dynamic
> > > initialization [...] 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.

> > Note that the alternative is not implementable in practice.

> Why not?

Because it is self contradictory in the case of cyclic
references. Consider the sentence (§3.6.2/3): "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." Now consider two translation units:

tu1.cc:
extern int f() ;
int a = f() ;

int
g()
{
return a ;
}

tu2.cc:
extern int g() ;
int b = g() ;

int
f()
{
return b ;
}

According to the standard, b is guaranteed to be initialized
before the first time f() is called, and a is guaranteed to be
initialized before the first time g() is called. How do you
propose to meet these two requirements?

> > > Are there any implementations that defer intialization of
> > > static objects in such a way (leaving dynamic libraries
> > > aside)?

> > No. And there never will be; too many programs count on
> > initialization before main.

> It is worth noting that there is at least one popular compiler
> (MSVC) that strips unreferenced static variables from *lib*
> files.

Are you sure? Every time someone has claimed this, it's turned
out that they've actually not incorporated the translation unit
with the static object into their program. And no compiler
initializes static objects which aren't part of the program.

There was at any rate no problem with VC++ 6.0. The free
downloadable version of later versions doesn't support building
libraries (at least as far as I can see), and I don't have
access to a more recent commercial version to verify, but I
would be surprised if they broke something this fundamental.

> Without precautions (disable stripping) static objects in such
> lib files can therefore not be used for registration schemes
> (where typically no code ever references the static variable).
> This is only the case if cpps are first compiled into lib
> files and then linked into the exe. If all .cpps are directly
> compiled into the exe then all statics are initialized before
> main().

Typically, you need to take special steps for such registration
schemes to work with statically linked libraries, because by
definition, a library is a collection of object files, each of
which will only be made part of the linked program if it
resolves an undefined external. This is true (hopefully) for
every compiler in existance. And of course, the only reason
such schemes work with DLL's is that DLL's aren't libraries, but
pre-linked object files. (Sort of. The presence of resources
does make them a library. But a library with a single object
file, and some other resources. Not multiple object files.)

> This behavior can be interpreted as deferred initialization,
> because the static is *never* accessed.

I'm not sure. Supposing this behavior really exists, the
standard states that "It is implementation-defined whether or
not the dynamic initialization of an object of namespace scope
is done before the first statement of main." Within the
standard, "implementation-defined" means that the implementation
must make a choice, and document it. So in theory, unless VC++
actually documents it this way, the argument doesn't hold. (I
say in theory, because in practice, I've yet to actually find
such documentation for any compiler I've actually used.)

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Thomas Kemmer

unread,
Jul 25, 2005, 9:25:55 AM7/25/05
to
ka...@gabi-soft.fr writes:

> Andreas Huber wrote:
>
> > It is worth noting that there is at least one popular compiler
> > (MSVC) that strips unreferenced static variables from *lib*
> > files.
>
> Are you sure? Every time someone has claimed this, it's turned
> out that they've actually not incorporated the translation unit
> with the static object into their program. And no compiler
> initializes static objects which aren't part of the program.
>
> There was at any rate no problem with VC++ 6.0. The free
> downloadable version of later versions doesn't support building
> libraries (at least as far as I can see), and I don't have
> access to a more recent commercial version to verify, but I
> would be surprised if they broke something this fundamental.

I think such behavior would actually violate 3.7.1 (2):

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 [...]

- Thomas

Andreas Huber

unread,
Jul 25, 2005, 11:23:07 AM7/25/05
to

Ok, I see. You do get rid of the standard's contradiction if you
initialize before main(). However, you don't get rid of the logical
contradiction. You won't get anything useful out of this code (a and b
will always be 0 after initialization).

> How do you
> propose to meet these two requirements?

For cyclic references you can't, but then again I don't think such
cyclic initialization is useful in practice.

> > > > Are there any implementations that defer intialization of
> > > > static objects in such a way (leaving dynamic libraries
> > > > aside)?
>
> > > No. And there never will be; too many programs count on
> > > initialization before main.
>
> > It is worth noting that there is at least one popular compiler
> > (MSVC) that strips unreferenced static variables from *lib*
> > files.
>
> Are you sure? Every time someone has claimed this, it's turned
> out that they've actually not incorporated the translation unit
> with the static object into their program. And no compiler
> initializes static objects which aren't part of the program.

Sorry for being unclear. The compiler didn't strip the static variables
from lib files. It stripped them at link-time when you incorporated the
lib into an exe, as you describe below.

> > Without precautions (disable stripping) static objects in such
> > lib files can therefore not be used for registration schemes
> > (where typically no code ever references the static variable).
> > This is only the case if cpps are first compiled into lib
> > files and then linked into the exe. If all .cpps are directly
> > compiled into the exe then all statics are initialized before
> > main().
>
> Typically, you need to take special steps for such registration
> schemes to work with statically linked libraries, because by
> definition, a library is a collection of object files, each of
> which will only be made part of the linked program if it
> resolves an undefined external.

True, but this is something a lot of people do not realize when they
talk about initialization time of static objects.

> > This behavior can be interpreted as deferred initialization,
> > because the static is *never* accessed.
>
> I'm not sure. Supposing this behavior really exists, the
> standard states that "It is implementation-defined whether or
> not the dynamic initialization of an object of namespace scope
> is done before the first statement of main." Within the
> standard, "implementation-defined" means that the implementation
> must make a choice, and document it. So in theory, unless VC++
> actually documents it this way, the argument doesn't hold.

Good point.

> (I
> say in theory, because in practice, I've yet to actually find
> such documentation for any compiler I've actually used.)

Yeah, the same here.

Regards,

--
Andreas Huber

When replying by private email, please remove the words spam and trap
from the address shown in the header.

ka...@gabi-soft.fr

unread,
Jul 26, 2005, 6:40:12 AM7/26/05
to

> > > Why not?

> > int
> > g()
> > {
> > return a ;

I should have used a + 1 here,

> > }
> >
> > tu2.cc:
> > extern int g() ;
> > int b = g() ;
> >
> > int
> > f()
> > {
> > return b ;

and b + 2 here, if only because it would have made the order of
initialization issues clearer.

> > }

> > According to the standard, b is guaranteed to be initialized
> > before the first time f() is called, and a is guaranteed to
> > be initialized before the first time g() is called.

> Ok, I see. You do get rid of the standard's contradiction if
> you initialize before main(). However, you don't get rid of
> the logical contradiction. You won't get anything useful out
> of this code (a and b will always be 0 after initialization).

Roughly speaking: we all know that code like the above can't
work. If the implementation initializes before main, that's
your tough luck; you shouldn't write such code. If the
implementation initializes after main, however, the standard
says that the code must work -- it's the implementations problem
as to how to do this impossible feat.

> > How do you propose to meet these two requirements?

> For cyclic references you can't, but then again I don't think
> such cyclic initialization is useful in practice.

There's nothing in the standard that requires a C++ program to
be useful in order to be conforming:-).

> > > > > Are there any implementations that defer intialization
> > > > > of static objects in such a way (leaving dynamic
> > > > > libraries aside)?

> > > > No. And there never will be; too many programs count on
> > > > initialization before main.

> > > It is worth noting that there is at least one popular
> > > compiler (MSVC) that strips unreferenced static variables
> > > from *lib* files.

> > Are you sure? Every time someone has claimed this, it's
> > turned out that they've actually not incorporated the
> > translation unit with the static object into their program.
> > And no compiler initializes static objects which aren't part
> > of the program.

> Sorry for being unclear. The compiler didn't strip the static
> variables from lib files. It stripped them at link-time when
> you incorporated the lib into an exe, as you describe below.

Note carefully. The wording is important. Nobody stripped the
static variables from anything. You didn't specify correctly to
the compiler/linker that the translation units in question were
part of your program. You told the compiler/linker to include
them in your program if and only if the translation unit
resolved an external symbol which would not be otherwise
resolved. The compiler/linker are doing exactly what you asked
them to do.

> > > Without precautions (disable stripping) static objects in
> > > such lib files can therefore not be used for registration
> > > schemes (where typically no code ever references the
> > > static variable). This is only the case if cpps are first
> > > compiled into lib files and then linked into the exe. If
> > > all .cpps are directly compiled into the exe then all
> > > statics are initialized before main().

> > Typically, you need to take special steps for such
> > registration schemes to work with statically linked
> > libraries, because by definition, a library is a collection
> > of object files, each of which will only be made part of the
> > linked program if it resolves an undefined external.

> True, but this is something a lot of people do not realize
> when they talk about initialization time of static objects.

I know. The question seems to come up regularly, almost a FAQ.
It bothers me because 1) it seems to show an ignorance of the
basic tools -- what is a library, and what does a linker do, and
2) if you think about it, you don't really want the linker to
incorporate every single module in every single library you
specify to it.

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

0 new messages