崩溃后如何制作“不可能”的堆栈跟踪?

时间:2013-04-26 02:33:55

标签: c++ macos stack-trace crash-reports wakeup

我的程序似乎正在遭受一个非常难以重现的错误:一旦进入了一个蓝色的月亮,当用户让他的Mac进入睡眠状态,之后再次将其唤醒时,我程序中的一个子进程将崩溃在Mac醒来之后立即。

当发生这种情况时,Apple的崩溃报告机制可靠地报告像这样的堆栈跟踪:

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0   libsystem_kernel.dylib          0x967f9a6a __pthread_kill + 10
1   libsystem_c.dylib               0x9003dacf pthread_kill + 101
2   libsystem_c.dylib               0x900744f8 abort + 168
3   com.meyersound.VirtualD-Mitri   0x0014438e muscle::CrashSignalHandler(int) + 190
4   libsystem_c.dylib               0x9002886b _sigtramp + 43
5   ???                             0xffffffff 0 + 4294967295
6   com.meyersound.VirtualD-Mitri   0x001442d0 muscle::ParsePortArg(muscle::Message const&, muscle::String const&, unsigned short&, unsigned long) + 80
7   com.meyersound.VirtualD-Mitri   0x005b3393 qnet::RepDBPeer::Pulse(muscle::PulseNode::PulseArgs const&) + 1187
8   com.meyersound.VirtualD-Mitri   0x0015717b muscle::PulseNode::PulseAux(unsigned long long) + 203
9   com.meyersound.VirtualD-Mitri   0x000cfb90 muscle::ReflectServer::ServerProcessLoop() + 3232
10  com.meyersound.VirtualD-Mitri   0x00607c7e dcasldmain(int, char**) + 2222
11  com.meyersound.VirtualD-Mitri   0x0072c14d dmitridmain(int, char**) + 4749
12  com.meyersound.VirtualD-Mitri   0x0000bc3a main + 4938
13  com.meyersound.VirtualD-Mitri   0x000061ab _start + 209
14  com.meyersound.VirtualD-Mitri   0x000060d9 start + 41

这一切都很好,除了(提示怪异的音乐) - 它逻辑上不可能。特别是,我的RepDBPeer::Pulse()方法不仅不会调用ParsePortArg,因此崩溃过程永远不会在任何地方调用ParsePortArg ! (我把我所有的源代码都用了两次来确保)

所以我的问题是,这个堆栈跟踪试图告诉我什么?这很可能是一个线程0的堆栈被严重破坏的情况,以至于堆栈跟踪机制已经脱离轨道并指责一个无辜的旁观者作为罪魁祸首?或者Apple的唤醒机制是否有可能以某种方式将程序计数器“跳”到ParsePortArg()中(由此导致的混乱导致崩溃)?还是还有一些其他更深层次的魔法,我甚至无法想象?

有问题的崩溃过程是一个vanilla非GUI后台进程,它是一个由Qt GUI进程产生的子进程,值得的。

1 个答案:

答案 0 :(得分:1)

我假设你已经开启了一些优化。叠加痕迹没有魔力。一旦代码被内联或省略,它们就变得越来越模糊(读作“不太准确”),这正是C ++优化器所做的。 在ParsePortArg的情况下,在该行的末尾有一个+80,这意味着在代码段中该函数的入口点之前80个字节。这表示0x001442d0处指令指针的真实地址,而ParsePortArg是堆栈转储猜测的最近符号。你认为这是一只红鲱鱼是对的。

除了任何其他数据,我会非常谨慎地猜测你的程序期望某些指针保持有效,从睡眠状态唤醒时无效。查看该地址指令的反汇编。我打赌一个内存地址正在尝试被读取。