dynamic initialization in the Standard and Stroustrup's book

S

subramanian100in

Consider the program x.cpp:

#include <cstdlib>
#include <string>

using namespace std;

class Test
{
static string str;
};

string Test::str;

int main()
{
return EXIT_SUCCESS;
}

In the above program, consider the initialization
string Test::str;
The above initialization belongs to dynamic initialization category.

As per the ISO/IEC-14882:2003 document in section "3.6.2
Initialization of non-local objects" paragraph 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.”

As per the above paragraph, whether the dynamic initialization of
Test::str is done before the first statement of main is IMPLEMENTATION-
DEFINED. Am I correct ?

But Bjarne Stroustrup, in his book "The C++ Programming Language -
Third Edition" (NOT the Special Third Edition) mentions the following
in page 252 in TC++PL in
section "10.4.9 Nonlocal Store":
"A variable defined outside any function (that is, global, namespace,
and class static variables) is initialized (constructed) before main()
is invoked"

So, as per the above statement of Stroustrup, the class static data
member "Test::str" should be initialized before main() is invoked,
WITH ALL COMPILERS ie WITH ALL IMPLEMENTATIONS. Is this understanding
of mine is correct ? If I am correct, then there seems to be a
disagreement between the above statement in Stroustrup's book in page
252 in section "10.4.9 Nonlocal Store" and the ISO/IEC-14882:2003
document in section "3.6.2 Initialization of non-local objects"
paragraph 3. Am I correct in this? If I am wrong kindly explain where
I have misunderstood.

Thanks
V.Subramanian
 
V

Victor Bazarov

Consider the program x.cpp:

#include <cstdlib>
#include <string>

using namespace std;

class Test
{
static string str;
};

string Test::str;

int main()
{
return EXIT_SUCCESS;
}

In the above program, consider the initialization
string Test::str;
The above initialization belongs to dynamic initialization category.

As per the ISO/IEC-14882:2003 document in section "3.6.2
Initialization of non-local objects" paragraph 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.”

As per the above paragraph, whether the dynamic initialization of
Test::str is done before the first statement of main is IMPLEMENTATION-
DEFINED. Am I correct ?

Uh... That's what the paragraph says, yes. Are you correct that it
says what it says? Yes, you are correct, I suppose.

Well, actually, it doesn't have to be done at all since 'Test::str' is
not used in the program.
But Bjarne Stroustrup, in his book "The C++ Programming Language -
Third Edition" (NOT the Special Third Edition) mentions the following
in page 252 in TC++PL in
section "10.4.9 Nonlocal Store":
"A variable defined outside any function (that is, global, namespace,
and class static variables) is initialized (constructed) before main()
is invoked"

OK. I don't have the book handy, so I will trust your ability to quote.
So, as per the above statement of Stroustrup, the class static data
member "Test::str" should be initialized before main() is invoked,
WITH ALL COMPILERS ie WITH ALL IMPLEMENTATIONS. Is this understanding
of mine is correct ?

Well, since the book doesn't say explicitly "with all compilers" or
"with all implementations", it could be understood differently
(depending on the context), but it wouldn't be unreasonable to assume
that Dr. Stroustrup meant "as a language requirement", i.e. for all
implementations.
> If I am correct, then there seems to be a
disagreement between the above statement in Stroustrup's book in page
252 in section "10.4.9 Nonlocal Store" and the ISO/IEC-14882:2003
document in section "3.6.2 Initialization of non-local objects"
paragraph 3. Am I correct in this? If I am wrong kindly explain where
I have misunderstood.

Well, the Standard allows for more flexibility. It is _reasonable_ to
assume that compilers out there (at least that's how they started)
actually perform dynamic initialization of all static objects *before*
main function is invoked. At the same time the Standard *allows* for an
implementation to exist that does delay the dynamic initialization
(calling of the constructor) for some objects to immediately before
their first use. Whether there is one out there that actually does, I
am not sure.

Yes, there is a disagreement. I would suggest asking Dr. Stroustrup
about it.

V
 
K

Kaz Kylheku

I believe this is a half-hearted attempt to support dynamic load
libraries.

It looks like an optimization possibility; obviously, it's defining lazy
construction: defer the construction of objects in modules until the
first use. If a module is never called during a particular execution of
the program, then its constructors don't have to happen.

Dynamic load libraries can, and do, deal with a ``construct everything
upfront'' order (e.g walk a section with pointers to functions to
constructors and call them all), but that means touching a lot of code
upfront. In a VM system, you're page-faulting in code that might not
even get to run.

But I don't see how this supports shared libraries in particular (or why
it's half-hearted); lazy global construction can boost statically linked
executables also.
 
A

Alf P. Steinbach

* Kaz Kylheku:
It looks like an optimization possibility; obviously, it's defining lazy
construction: defer the construction of objects in modules until the
first use. If a module is never called during a particular execution of
the program, then its constructors don't have to happen.

Dynamic load libraries can, and do, deal with a ``construct everything
upfront'' order (e.g walk a section with pointers to functions to
constructors and call them all), but that means touching a lot of code
upfront. In a VM system, you're page-faulting in code that might not
even get to run.

But I don't see how this supports shared libraries in particular (or why
it's half-hearted); lazy global construction can boost statically linked
executables also.

It supports dynamic libraries to some extent because without this wording a
dynamic late loading of a dynamic library would be even more at variance with
the standard.

On the other hand I think of "after the first statement of main" as a defect.

That wording is consistent with the support-of-dynamic-libraries interpretation
but it imposes different requirements depending on exactly when the library is
loaded: during the first statement of main, or after. With a strict reading,
/during/ the first statement of main you can use functions or objects in a
translation unit with no guarantee that other objects of namespace scope in that
translation unit have been dynamically initialized... Uh oh.


Cheers & hth.

- Alf
 
J

James Kanze

Uh... That's what the paragraph says, yes. Are you correct
that it says what it says? Yes, you are correct, I suppose.
Well, actually, it doesn't have to be done at all since
'Test::str' is not used in the program.

Actually, his statement was that it was implementation defined
whether the initialization of Test::str is done before the first
statement of main, and it's incorrect. The passage he quotes
clearly says that "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.” In this
case, main is a function in the same translation unit, so if the
implementation does (normally) defer initialization to some
later point in time, it still has to do it before main is used.
The relaxed rule doesn't affect objects defined in the same
translation unit as main. (The relaxed rule is also impossible
to implement correctly, since cyclic dependencies are possible,
and to my knowledge, no compiler has ever tried, so you can
pretty much ignore it.)
OK. I don't have the book handy, so I will trust your ability
to quote.
Well, since the book doesn't say explicitly "with all
compilers" or "with all implementations", it could be
understood differently (depending on the context), but it
wouldn't be unreasonable to assume that Dr. Stroustrup meant
"as a language requirement", i.e. for all implementations.

He could very easily simply be talking about what happens in
practice.
Well, the Standard allows for more flexibility. It is
_reasonable_ to assume that compilers out there (at least
that's how they started) actually perform dynamic
initialization of all static objects *before* main function is
invoked. At the same time the Standard *allows* for an
implementation to exist that does delay the dynamic
initialization (calling of the constructor) for some objects
to immediately before their first use. Whether there is one
out there that actually does, I am not sure.
Yes, there is a disagreement. I would suggest asking Dr.
Stroustrup about it.

If you go back in time, I think the rule allowing deferred
initialization originated with Stroustrup. I suspect that the
main motivation, *at the time*, was worries about program start
up times. This is a lot less relevant today, and the committee
more or less held onto the rule because of dynamic linking---an
object in a dynamically linked object cannot be initialized
before it is loaded, and if an implementation uses lazy loading
(or the dynamic object is explicitly loaded), then the
initialization will occur after main. But in the case of cycles
in the initialization, it may also occur after the first use of
a function or object in the translation unit, so the
implementation is still not conform, and I'm not sure that any
deferred linking can be considered conform---the standard does
say that linking is one of the phases of translation. (On the
other hand, if the code is correct, a conforming program
probably can't tell, and if it isn't, any errors normally
detected by the linker are undefined behavior, so anything the
system does is OK.)
 
J

James Kanze

It allows leeway for dynamically loaded libraries.

Except that:

All external object and function references are
resolved. Library components are linked to satisfy
external references to functions and objects not defined
in the current translation. All such translator output
is collected into a program image which contains
information needed for execution in its execution
environment.

is the last "phase of translation". Presumably, you can't
(legally, in a conforming manner) execute any of the program
until everything has been linked, and any dynamic linking is a
non-conforming extension, defined uniquely by the
implementation.

But can a conforming program tell, or is it allowed under the as
if rule? As far as I can tell, all of the "errors" which are
not detected until link time result in "undefined behavior"
(mostly violations of the ODR or exceeding resource limits), so
the fact that the dynamic link may fail doesn't necessarily make
it non-conforming.

Of course, if an implementation does exploit this leeway, I'll
immediately write a program for which it fails---the standard
wording makes no allowance for cyclic dependencies, and it's
rather easy to construct a case where the constructor of static
object A uses an object or a function in the translation unit
which contains object B (and thus, object B must be constructed
before object A) and vice versa.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,756
Messages
2,569,533
Members
45,007
Latest member
OrderFitnessKetoCapsules

Latest Threads

Top