An ag(e)ing hacker, Luca Saiu's blog
2021-11-18 22:00 (last update: 2022-11-26 18:37) Luca Saiu
Today Volker Birk and I were speaking over lunch about object initialisation in C++ and about how weakly defined a program entry point is, because of objects with static storage duration.
Volker wrote a short program whose output changes after reversing the
order of two variable definitions, both out of a main
function
whose entire body was return 0;
.
He discussed it
in German, on his blog.
I was more annoyed by the fact that initialisation order is not guaranteed to respect functional dependency across compilation units. Here is my test case, where GCC and the GNU linker exhibit the counter-intuitive (but conformant) behaviour.
Let us define a simple class foo
with a non-default constructor
logging initialisation to stdout
, in a header named h.hh:
#include <iostream> class foo { public: int x; foo (int x_) : x (x_) { std::cout << "Initializing a foo at " << this << "\n"; std::cout << "its field will be " << x << "\n"; } };
This file q.cc uses a foo
variable f1
defined
elsewhere to initialise another foo
variable f2
; here
it would appear reasonable to assume that the current compilation unit
could see f1
as already completely initialised, with an
extern
declaration:
#include <iostream> #include "h.hh" extern foo f1; foo f2 = f1.x + 1; int main () { std::cout << f2.x << "\n"; return 0; }
The definition of f1
is in this file, w.cc:
#include "h.hh" foo f1 = 4;
And now we can play around by referencing the two files in different orders on the command line of the compiler driver.
Here I am passing w.cc before q.cc...
g++ -O3 w.cc q.cc && ./a.out
...which yields the intuitive behaviour: f1
is indeed
initialised before f2
.
Initializing a foo at 0x55cbc03b9194 its field will be 4 Initializing a foo at 0x55cbc03b919c its field will be 5 5
However it is easy to observe a different behaviour:
g++ -O3 q.cc w.cc && ./a.out
By changing the order of the two files here we can see the f1
field set to zero when f2
is initialised — f1
’s
constructor running after f2
’s:
Initializing a foo at 0x565447237194 its field will be 1 Initializing a foo at 0x56544723719c its field will be 4 1
We were surprised to discover, after consulting the Standard http://www.open-std.org/jtc1/sc22/wg21/ (see §3.6.2 in n3797.pdf, p.59 near the bottom and then the next page) that in fact this preliminary zero-initialisation is guaranteed1 to happen before the actaual static or dynamic initialisation:
§3.6.2, point 2: Variables with static storage duration (3.7.1) or thread storage duration (3.7.2) shall be zero-initialized (8.5) before any other initialization takes place.
Notice that the behaviour of GCC and GNU ld is indeed conformant:
§3.6.2, point 2 [my emphasys]: If a program starts a thread (30.3), the subsequent initialization of a variable is unsequenced with respect to the initialization of a variable defined in a different translation unit. Otherwise, the initialization of a variable is indeterminately sequenced with respect to the initialization of a variable defined in a different translation unit.
This happens with every GCC version I have tested, from version 4 to version 11. I only tried on x86_64 and MIPS, but there is no reason to expect a different behaviour on other architectures.
In defence of the Standard I have to concede that the alternative of providing guarantees about initialisation order without failing at link or initialisation time is not realistic: it would be very easy to build a cycle of two variables mutually depending on each other for initialisation, across two compilation units.
— Luca Saiu, 2021-11-18 22:00 (last update: 2022-11-26 18:37)
Tags: c++, english, free-software, gcc, gnu, myself, p≡p |
Next post | Previous post |
You might want to go to
the
main blog index
(feeds for every post:
Atom 1.0,
RSS 2.0)
or to my web site
https://ageinghacker.net
.
Luca Saiu |
The opinions I express here are my own and do not
necessarily reflect the beliefs or policies of my
employer or for that matter of anyone else. In case you
felt that the public statement of my thoughts threatened
your warm sense of security and your emotional stability
feel free to leave at any time.
You might be interested in my web site
|
Copyright © 2009, 2011-2014, 2017, 2018, 2021-2024 Luca Saiu
Verbatim copying and redistribution of this entire page are permitted
in any medium without royalties, provided this notice is preserved.
This page was generated by trivialblog.
trivialblog is
free software,
available under the
GNU GPL.
Tag icon copyright information is available
in this file.
Within the limits of as-if semantics, of course. But the behaviour is easily observable.