同一段c++代码在g++ 4.6编译器中可以工作,但在5.1编译器中会崩溃
same piece of C++ code works in g++ 4.6 compiler but crashes with 5.1
下面的代码在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 ()
为什么在c++中使用__attribute__((constructor))
,而不是简单地使用带有构造函数的全局对象?这些属性在C代码中很有用,但在c++中是多余的。
问题是你的构造函数在标准iostreams初始化之前运行,如果你在构造函数中使用全局对象,这不会是一个问题。
你可以试着给你的构造函数增加一个优先级,但我不认为它在这种情况下会有帮助:
__attribute__((constructor(999)))
在gcc 4.9.2中也会出现运行时错误(参见ideone示例)。
问题与iostreams尚未初始化有关。注释掉cerr
行,一切正常
显然,这是一个已知的问题。
编辑:附加备注
这个小的解决方法似乎是有效的,至少在4.9:使用c stdio而不是iostreams:
fprintf(stderr, "_initialize"); // this works
但是我完全同意Jonathan的建议,使用全局(单例?)对象完全依赖于定义良好的标准c++行为,除非你真的需要构造函数恰好在动态库加载的那一刻运行。
相关文章:
- 这个C++编译器优化(在自身的实例上调用对象自己的构造函数)的名称是什么,它是如何工作的?
- 编译"运算符删除"时C++编译器如何工作?
- 虚拟基类在内部如何工作?编译器如何解析对基方法的调用?
- 检查工作正常的 CXX 编译器:/cygdrive/c/cygwin64/bin/clang++ -- 已损坏
- 交叉编译器树莓派不完整类型,而本机编译器工作
- C++编译器 g++.exe 无法编译简单的测试程序 - 确定 CXX 编译器是否工作失败
- 切换到新编译器后,SSCANF 的工作方式有所不同
- 编译器生成的默认构造函数工作 - C++
- boost binary_oarchive 对于不同的编译器,其工作方式不同
- C++ - 我使用哪个编译器来使自动 eq = [ ](..) 语法工作?
- 可视化C++工作区和编译器.你好世界测试初学者
- g++ 编译器的内部工作原理,用于傻瓜
- 编译器指令在C++中的工作
- 比较运算符重载,为什么编译器不做工作?
- MinGW编译器为pip "cannot find vcvarsall.bat"错误后,仍然无法正常工作
- 在正向声明的情况下,编译器是如何工作的,Makefile是如何发挥作用的
- g++编译器为表达式提供<<类型错误,但在Visual Studio中工作
- 编译器问题:iostream不工作
- 名称篡改如何与使用不同编译器编译的DLL和LIB一起工作
- Arduino左移未按预期工作,编译器错误