是什么导致了我的堆栈中神秘的重复条目?

时间:2009-10-29 20:26:25

标签: c++ linux debugging gdb g++

我正在调查死锁错误。我使用gcore获取了一个核心,发现我的一个函数似乎已经调用了自己 - 即使它进行递归函数调用。

这是gdb的堆栈片段:

Thread 18 (Thread 4035926944 (LWP 23449)):
#0  0xffffe410 in __kernel_vsyscall ()
#1  0x005133de in __lll_mutex_lock_wait () from /lib/tls/libpthread.so.0
#2  0x00510017 in _L_mutex_lock_182 () from /lib/tls/libpthread.so.0
#3  0x080d653c in ?? ()
#4  0xf7c59480 in ?? () from LIBFOO.so
#5  0x081944c0 in ?? ()
#6  0x081944b0 in ?? ()
#7  0xf08f3b38 in ?? ()
#8  0xf7c3b34c in FOO::Service::releaseObject ()
   from LIBFOO.so
#9  0xf7c3b34c in FOO::Service::releaseObject ()
   from LIBFOO.so
#10 0xf7c36006 in FOO::RequesterImpl::releaseObject ()
   from LIBFOO.so
#11 0xf7e2afbf in BAR::BAZ::unsubscribe (this=0x80d0070, sSymbol=@0xf6ded018)
    at /usr/lib/gcc/x86_64-redhat-linux/3.4.6/../../../../include/c++/3.4.6/bits/stl_tree.h:176
...more stack

我已经省略了一些名字:FOO& BAR是namespaces.BAZ是一个类。

有趣的部分是#8和#9,对Service::releaseObject()的调用。此函数不会调用自身,也不调用任何调用它的函数...它是递归。为什么它会在堆栈中出现两次?

这是一个由调试器创建的人工制品,还是真的?

您会注意到最里面的呼叫正在等待互斥锁 - 我认为这可能是我的僵局。 Service::releaseObject()锁定一个互斥锁,所以如果它神奇地传送回自身内部,那么肯定会发生死锁。

一些背景:

这是在RHEL4上使用g ++ v3.4.6编译的。它是一个64位操作系统,但这是32位代码,使用-m32编译。它在-O3进行了优化。我无法保证应用程序代码的编译与LIBFOO代码完全相同。

Service没有虚函数,因此没有vtable。类RequesterImpl继承自全虚拟接口,因此它具有vtable。

2 个答案:

答案 0 :(得分:4)

在任何优化级别的x86上,Stacktraces都是不可靠的:-O1和更高的启用-fomit-frame-pointer

答案 1 :(得分:3)

你得到“坏”堆栈的原因是__lll_mutex_lock_wait有不正确的展开描述符(它是用手工编码的汇编编写的)。我相信这在最近(2008年)有所修复,但找不到确切的补丁。

一旦GDB堆栈展开器“失去平衡”,它会创建虚假帧(#2到#8),但最终会在使用帧指针的帧上发生故障,并为其余的帧生成正确的堆栈跟踪堆栈。