According to C++11 specification:
The results of including
<iostream>
in a translation unit shall be as if<iostream>
defined an instance ofios_base::Init
with static storage duration. Similarly, the entire program shall behave as if there were at least one instance ofios_base::Init
with static storage duration
This implies that if my code looks like that:
// A.cpp
#include <iostream>
using namespace std;
unsigned long foo() {
cerr << "bar";
return 42;
}
and
// B.cpp
using namespace std;
extern unsigned long foo();
namespace {
unsigned long test() {
int id = foo();
return id;
}
unsigned long id = test();
}
int main() {
return 0;
}
then I should be safe calling cerr
without the risk of a static initialization fiasco.
Unfortunately, that code segfaults... Why? I don't think gcc 6.2.1 decided to ignore the C++11 specification, and I included <iostream>
in A.cpp. According to the specification it should suffice.
The full quote of the paragraph includes:
The objects are constructed and the associations are established at some time prior to or during the first time an object of class ios_base::Init is constructed, and in any case before the body of main begins execution. 293)
And with the footnote
293) If it is possible for them to do so, implementations are encouraged to initialize the objects earlier than required.
So, the guarantee is that the iostreams will work at the latest when entering main. There is no strict requirement that they should work earlier, unless the translation unit includes <iostream>
.
You have found a way to circumvent this!
When calling foo()
from B.cpp, the ios_base::Init
instance included in A.cpp may, or may not, have been initialized.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With