在静态变量初始化中使用cout时的C++分段错误

gex*_*ide 12 c++ cout initialization segmentation-fault

我有一个程序,我使用cout发出调试信息.代码在静态全局变量的初始化中执行,即在程序执行的早期.当我使用自己的构建脚本来构建程序时,它首次使用cout时会出现段错误(只有字符串文字被转移到cout中,所以它不能是值).我使用valgrind检查早期写入无效位置,但没有(并且也没有可能生成这些写入的代码,我在输出之前不做太多).当我将源代码复制到eclipse项目并让eclipse内置构建器构建它时,一切正常.我没有使用简单编译的奇怪的构建器设置-ggdb -std=c++0x,这些是唯一的两个标志.

那么,如果之前没有无效的写入,那么带有字符串文字段错误的cout可能是什么原因?构建配置如何影响这个?

(对不起,我不能给你一个最小的例子,因为这个例子可以简单地在你的机器上编译,就像在使用eclipse构建器时那样)

编辑:这是堆栈跟踪:

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
Run Code Online (Sandbox Code Playgroud)

最后一帧是我的代码.第92行简单地写道:

std::cout << "Test";
Run Code Online (Sandbox Code Playgroud)

Luc*_*ore 13

std::cout是静态存储中的对象.它保证在进入之前进行初始化main,但不一定在代码中的其他静态之前进行初始化.看起来像静态初始化命令fiasco.

经过一番挖掘:

27.4.2.1.6类ios_base :: Init

Init ();

3)效果:构造类Init的对象.如果init_cnt为零,则函数将值1存储在init_-cnt中,然后构造并初始化对象cin,cout,cerr,clog(27.3.1),wcin,wcout,wcerr和wclog(27.3.2).在任何情况下,函数然后将一个值添加到存储在init_cnt中的值.


Jam*_*nze 12

正如Luchian指出的那样,在构造std::cout第一个实例之前你不能使用ios_base::Init.但是,您不必定义实例; 包括<iostream>应该就够了.

初始化的顺序一个翻译单元中定义的.如果您<iostream>在所有具有静态实例的文件的顶部包含,那么您应该没问题.但是,如果静态对象的构造函数在另一个转换单元中调用函数,并且输出在该转换单元中,则<iostream> 仅包括在执行输出的转换单元中是不够的.您必须将其包含在定义静态变量的转换单元中.即使他们没有做任何输出.