I have a program where I use cout to emit debug information. The code is executed in the initialization of a static global variable, i.e. quite early in the program execution. When I use my own build script to build the program, it segfaults at the first use of cout (only a string literal is shifted into cout, so it cannot be the value). I used valgrind to check for earlier writes to invalid locations, but there are none (and there is also no code that would be likely to generate those writes, I dont do too much before the output). When I copy the source code to an eclipse project and let the eclipse built-in builder build it, then everything works fine. I used no weird builder settings simply compiled with -ggdb -std=c++0x
, these are the only two flags.
So what can be the reason that a cout with a string literal segfaults, if there were no invalid writes before? How can the build configuration affect this?
(I am sorry I can give you no minimal example, as this example would simply compile fine at your machine, as it does for me when using the eclipse builder)
Edit: Here is the stacktrace:
0x00007ffff7b6d7d1 in std::ostream::sentry::sentry(std::ostream&) () from /usr/lib /x86_64-linux-gnu/libstdc++.so.6
(gdb) backtrace
#0 0x00007ffff7b6d7d1 in std::ostream::sentry::sentry(std::ostream&) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#1 0x00007ffff7b6dee9 in std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long) ()
from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#2 0x00007ffff7b6e2ef in std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*) ()
from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#3 0x00000000004021be inTest::fill (this=0x6120f8, funcs=...) at inTest.cpp:92
The last frame is my code. Line 92 simply reads:
std::cout << "Test";
As Luchian has pointed out, you cannot use
std::cout
before the first instance ofios_base::Init
has been constructed. You don't have to define an instance, however; including<iostream>
should be enough.Order of initialization is defined within a single translation unit. If you include
<iostream>
at the top of all files which have static instances, you should be OK. If the constructor of a static object calls a function in another translation unit, however, and the output is in that translation unit, it is not sufficient to include<iostream>
only in the translation unit which does the output. You must include it in the translation unit where the static variable(s) are defined. Even if they don't do any output.std::cout
is an object in static storage. It's guaranteed to be initialized before enteringmain
, but not necessarily before other statics in your code. Seems like the static initialization order fiasco.After some digging:
27.4.2.1.6 Class ios_base::Init
Static variable initialization is a no-man's-land. You will avoid problems if you avoid doing significant work there. Maybe you should wrap the static variable in a Singleton pattern so you can defer initialization to the first time it's used.