C++ SIGSEGV in_dl_fini
我希望能对调试一个我已经苦思冥想了两天的问题有所了解。情况就是这样C++ SIGSEGV in_dl_fini,c++,debugging,gdb,segmentation-fault,C++,Debugging,Gdb,Segmentation Fault,我希望能对调试一个我已经苦思冥想了两天的问题有所了解。情况就是这样 我正在处理两个共享对象文件,我们称它们为libMyA.so和libMyB.so,它们是产品的一部分 这两个共享对象文件分别链接两个静态库,libMyC.a和libMyD.a libMyA.so和libMyB.so我有一些单元测试,它们基本上是命令行可执行文件,调用共享对象导出的一些函数,blackboxA和blackboxB libMyB.so使用了由libMyA.so导出的函数。在libMyB.so的init函数中调用了li
- 我正在处理两个共享对象文件,我们称它们为
和libMyA.so
,它们是产品的一部分libMyB.so
- 这两个共享对象文件分别链接两个静态库,
和libMyC.a
libMyD.a
和libMyA.so
我有一些单元测试,它们基本上是命令行可执行文件,调用共享对象导出的一些函数,libMyB.so
和blackboxA
blackboxB
使用了由libMyB.so
导出的函数。在libMyA.so
的init函数中调用了libMyB.so
的一些函数(只是生成了一些STL容器)libMyA.so
运行平稳,通过所有测试blackboxA
也通过了所有测试,但在终止时它会引发一个blackboxB
SIGSEGV
SIGSEGV
发生在执行libMyB的终结器期间。因此在std::basic_string
对象的析构函数内:
#0 0x00007ffff74a0bc3 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#1 0x00007ffff74a0c13 in std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#2 0x00007ffff6b6cd1d in __cxa_finalize (d=0x7ffff7dd4d80) at cxa_finalize.c:56
#3 0x00007ffff7b1d7b6 in __do_global_dtors_aux () from ./libMinosCVC.so.3
#4 0x00007fffffffe3a0 in ?? ()
#5 0x00007fffffffe480 in ?? ()
#6 0x00007ffff7b9a541 in _fini () from ./libMinosCVC.so.3
#7 0x00007fffffffe480 in ?? ()
#8 0x00007ffff7de992d in _dl_fini () at dl-fini.c:259
#0 0x00007ffff74a0bc3英寸??()来自/usr/lib/x86_64-linux-gnu/libstdc++.so.6
#1 0x00007FF74A0C13,位于/usr/lib/x86_64-linux-gnu/libstdc++.so.6中的std::basic_string::~basic_string()
#2 0x00007FF6B6CD1D位于cxa_finalize处的cxa_finalize(d=0x7ffff7dd4d80)中。c:56
#3 0x00007FF7B1D7B6 in u do_global_dtors_aux(),来自./libMinosCVC.so.3
#4 0x00007FFFFFE3A0英寸??()
#5 0x00007FFFFFE480英寸??()
#6 0x00007FF7B9A541 in_fini()来自./libMinosCVC.so.3
#7 0x00007FFFFFE480英寸??()
#8 0X00007FF7DE992D在dl fini.c处的dl fini()中:259
我知道,在静态库的全局或命名空间范围内定义的std::string对象可能会有问题,因为该静态库在这个过程中由多个共享对象链接,并且已经浏览了libMyC.a
和libMyD.a
,但迄今为止没有成功
我还修改了blackboxB
,使主函数只包含返回0
,SIGSEGV
。如果我在init函数中修改libMyB.so
以更长时间调用libMyA.so
中的任何内容,SIGSEGV
将消失
当SIGSEGV发生时,是否有我不知道的方法来检测libc试图清理的实际对象?gdb确实指出了std::string
析构函数,但除此之外,没有其他东西(甚至无法访问std::string
成员)。valgrind也帮不了什么忙
哦,我差点忘了上面的樱桃:当用-O0构建时,一切都正常,只有-O2构建崩溃
感谢您对这场噩梦的任何意见……注意:这个答案是由一位希望匿名但希望有所帮助的同事提供给我的。我在解决这个问题上没有任何功劳。
我在工作中遇到了类似症状的问题。
这个答案概括了我是如何解决这个问题的。
大部分/所有这些信息都可以在互联网上的其他地方找到,但我找不到像这样整合的信息,而且,作为一个不“知情”的人,它在一开始对我来说不是非常明显(现在对我来说只是稍微明显一点)。
如果我做错了什么事,请提前道歉
有关我正在使用的机器的一些信息:
$cat/etc/redhat版本
Red Hat Enterprise Linux Server 6.9版(圣地亚哥)
$g++--版本
g++(GCC)4.4.7 20120313(红帽4.4.7-18)
...
$/lib64/libc.so.6
GNU C库稳定版本2.12,由Roland McGrath等人。
...
$uname-srm
Linux 2.6.32-696.6.3.el6.x86_64 x86_64
一个简单的工作示例:
common.h
:
#包括
结构公共{
静态常量std::字符串s;
};
common.cpp
:
#包括“common.h”
常量std::字符串Common::s(“Common”);
main.cpp
:
#包括
#包括“common.h”
内部主(空){
std::cout silent
>printf“$rdi%p$rsi%p\n”,$rdi,$rsi
>英国电信4号
>c
>结束
(gdb)设置pag关闭
(gdb)将日志重定向设置为打开
(gdb)设置日志文件_cxa_atexit.txt
(gdb)设置登录
将输出重定向到_cxa_atexit.txt。
(gdb)启动
(gdb)设置注销
已完成对uu cxa_atexit.txt的日志记录。
(gdb)
请注意,上面的pag/日志设置是可选的。
在本例中差别不大,但在我使用的“实际”程序中,\uuucxa\uAtexit
断点达到了数千次(并且花了几分钟到达main
处的临时断点)
在输出中查找重复的寄存器行:
grep“^\$rdi”\uuucxa\u atexit.txt | sort | uniq-d
我在%rdi
中检查地址,作为感觉良好的理智检查:
(gdb)x/i 0x。。。
0x…:。。。
$c++过滤器_ZNSsD2Ev
std::basic_string::~basic_string()
或者,使用gdb的i shared
或i proc map
列表获取偏移量,并在相应的二进制文件上使用反汇编程序(不要忘记)
相关的回溯如下所示:
#0 0x…在/lib64/libc.so.6的uuucxa_atexit_internal()中
#1 0x…在公共点的静态初始化和销毁中。cpp:2
#2 0x…在全局构造函数中,在common.cpp处键入common.cpp(void)()。cpp:2
#3 0x…在libone.so中的全局系数
如果查看第3帧中列出的二进制文件,即第1帧中列出的指令之前的一些指令,您应该看到在调用\uucxa\uAtexit
之前加载到%rsi
的内容。
在本例中,objdump使用“绝对偏移量”和\u ZN6Common1sE@@Base-0x80对其进行注释。
“绝对偏移”应符合以下要求: