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
    导出的函数。在
    libMyB.so
    的init函数中调用了
    libMyA.so
    的一些函数(只是生成了一些STL容器)
结果是:

  • blackboxA
    运行平稳,通过所有测试
  • blackboxB
    也通过了所有测试,但在终止时它会引发一个
    SIGSEGV
gdb告诉我,
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对其进行注释。
“绝对偏移”应符合以下要求: