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



>我有一个程序,我在其中使用 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

最后一帧是我的代码。第92行简单地说:

std::cout << "Test";

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

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

std::cout是静态存储中的一个对象。它保证在输入main之前初始化,但不一定在代码中的其他静力学之前。似乎是静态初始化顺序的惨败。

经过一番挖掘:

27.4.2.1.6 类 ios_base::初始化

Init ();

3(效果:构造一个类Init的对象。如果init_cnt是 零,函数将值 1 存储在 init_- cnt 中,然后 构造并初始化对象 cin, cout, cerr, clog (27.3.1(, WCIN、WCOUT、WCERR 和 WCLOG (27.3.2(。无论如何,函数然后 将 1 添加到存储在 init_cnt 中的值。

静态变量初始化是一个无人区。 如果你避免在那里做大量工作,你将避免问题。 也许您应该将静态变量包装在单例模式中,以便可以将初始化推迟到第一次使用时。

相关内容

  • 没有找到相关文章

最新更新