是啥导致我的堆栈中出现神秘的重复条目?

Posted

技术标签:

【中文标题】是啥导致我的堆栈中出现神秘的重复条目?【英文标题】:What caused the mysterious duplicate entry in my stack?是什么导致我的堆栈中出现神秘的重复条目? 【发布时间】:2009-10-29 20:26:24 【问题描述】:

我正在调查一个死锁错误。我用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 是命名空间。BAZ 是一个类。

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

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

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

一些背景:

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

Service 类没有虚函数,所以没有 vtable。 RequesterImpl 类继承自全虚拟接口,因此它确实有一个 vtable。

【问题讨论】:

【参考方案1】:

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

【讨论】:

那么,gdb 会将丢失的帧指针解释为堆栈中的重复函数吗? 是的,很可能同一个函数的第二个明显实例实际上是一个无框架函数。 这个答案不正确:对于 32 位代码 -fomit-frame-pointer 没有被任何 -O 优化级别选择。 不过,MSVC 的调试器通常可以处理丢失的帧指针。 嗯,阅读 GCC 源代码表明您确实是正确的:x86 在所有优化级别都启用了帧指针。 x86_64 通常(所有非 Mach-O)在任何非零优化级别都省略帧指针,其他几个架构也是如此;这一定是我得到这个概念的地方。【参考方案2】:

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

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

【讨论】:

太棒了。这完美地解释了它。谢谢。

以上是关于是啥导致我的堆栈中出现神秘的重复条目?的主要内容,如果未能解决你的问题,请参考以下文章

使用 C# 和 SQL 解决 datagridview 中重复条目的最佳方法是啥?

Access 2010 中的组合框重复选项

MySQL 高分 - 用户的个人排名:重复的条目导致不正确的值

Access VBA:关闭表单会导致表中的重复条目

列表项的神秘间距[重复]

iphone:setObject:forKey:和setValue:forKey:在将条目添加到可变字典中的区别是啥[重复]