C++ Segmentation Fault when using cout in static v

2020-07-03 06:26发布

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";

3条回答
ら.Afraid
2楼-- · 2020-07-03 07:07

As Luchian has pointed out, you cannot use std::cout before the first instance of ios_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.

查看更多
够拽才男人
3楼-- · 2020-07-03 07:13

std::cout is an object in static storage. It's guaranteed to be initialized before entering main, 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

Init ();

3) Effects: Constructs an object of class Init. If init_cnt is zero, the function stores the value one in init_- cnt , then constructs and initializes the objects cin, cout, cerr, clog (27.3.1), wcin, wcout, wcerr, and wclog (27.3.2). In any case, the function then adds one to the value stored in init_cnt .

查看更多
淡お忘
4楼-- · 2020-07-03 07:20

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.

查看更多
登录 后发表回答