在静态变量初始化中使用 cout 时出现 C++ 分段错误
我有一个程序,我使用 cout 来发出调试信息.代码在静态全局变量的初始化中执行,即在程序执行的早期.当我使用自己的构建脚本构建程序时,它在第一次使用 cout 时出现段错误(只有一个字符串文字被转移到 cout,所以它不能是值).我使用 valgrind 检查早期对无效位置的写入,但没有(也没有可能生成这些写入的代码,我在输出之前没有做太多).当我将源代码复制到 Eclipse 项目并让 Eclipse 内置构建器构建它时,一切正常.我没有使用任何奇怪的构建器设置,只是用 -ggdb -std=c++0x
编译,这是仅有的两个标志.
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.
那么,如果之前没有无效写入,带有字符串文字的 cout 段错误的原因是什么?构建配置对此有何影响?
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?
(对不起,我不能给你一个最小的例子,因为这个例子可以简单地在你的机器上编译,就像我在使用 eclipse builder 时所做的那样)
(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)
这是堆栈跟踪:
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 行简单地写着:
The last frame is my code. Line 92 simply reads:
std::cout << "Test";
推荐答案
正如 Luchian 所指出的,你不能在第一个之前使用 std::cout
ios_base::Init
的实例已构建.你不必然而,定义一个实例;包括 <iostream>
应该就够了.
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.
初始化顺序是在单个翻译单元中定义的.如果您在所有具有静态的文件的顶部包含 <iostream>
实例,你应该没问题.如果静态对象的构造函数然而,在另一个翻译单元中调用一个函数,输出是在该翻译单元中,仅包含 <iostream>
是不够的仅在执行输出的翻译单元中.你必须包括它在定义静态变量的翻译单元中.甚至如果他们不做任何输出.
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.
相关文章