以下代码与g ++ 4.6编译器一起使用,但在使用g ++ 5.1编译器编译时崩溃并出现分段错误。变量访问gString导致分段错误。
#define _GLIBCXX_DEBUG 1
#define _GLIBCXX_USE_CXX11_ABI 0
#include<string>
#include<iostream>
#include<vector>
static std::string gString("hello");
static void
__attribute__((constructor))
initialize()
{
gString.assign("hello world");
return;
}
static void
__attribute__((destructor))
finalize()
{
return;
}
int main(int ac, char **av)
{
//std::cerr<<gString;
return 0;
}
GDB输出:
Reading symbols from /home/rk/str...done.
(gdb) b initialize
Breakpoint 1 at 0x401419: file str.cc, line 15.
(gdb) r
Starting program: /home/rk/str
Breakpoint 1, initialize() () at str.cc:15
15 gString.assign("hello world");
(gdb) n
Program received signal SIGSEGV, Segmentation fault.
0x00000000004018d6 in std::string::size() const () at /usr/include/c++/5/bits/basic_string.h:3118
3118 { return _M_rep()->_M_length; }
(gdb) bt
#0 0x00000000004018d6 in std::string::size() const () at /usr/include/c++/5/bits/basic_string.h:3118
#1 0x00000000004016ff in std::string::assign(char const*, unsigned long) () at /usr/include/c++/5/bits/basic_string.tcc:706
#2 0x000000000040166e in std::string::assign(char const*) () at /usr/include/c++/5/bits/basic_string.h:3542
#3 0x0000000000401428 in initialize() () at str.cc:15
#4 0x00000000004023dd in __libc_csu_init ()
#5 0x00007ffff71ad700 in __libc_start_main () from /lib/x86_64-linux-gnu/libc.so.6
#6 0x0000000000401289 in _start ()
答案 0 :(得分:4)
为什么在C ++中使用__attribute__((constructor))
而不是简单地使用构造函数的全局对象?这些属性在C代码中很有用,但在C ++中是多余的。
问题是你的构造函数在初始化标准iostream之前运行,如果你使用带有构造函数的全局对象,这不会有问题。
您可以尝试为构造函数添加优先级,但我认为在这种情况下它不会有用:
__attribute__((constructor(999)))
答案 1 :(得分:3)
gcc 4.9.2也会发生运行时错误(参见ideone示例)。
问题与尚未初始化的iostream有关。评论cerr
行,一切正常
显然,它是known issue。
这个小workaround似乎有效,至少4.9:使用c stdio代替iostreams:
fprintf(stderr, "_initialize"); // this works
但我完全同意Jonathan关于使用完全依赖于明确定义的标准C ++行为的全局(单例?)对象的建议,除非您确实需要在动态库加载时正好运行构造函数。