从另一个线程打印堆栈跟踪

时间:2011-01-22 00:06:34

标签: iphone objective-c stack-trace

我知道我可以使用backtrace()或[NSThread callStackSymbols]获取当前线程的堆栈跟踪,但是我如何获得不同线程的堆栈跟踪(假设它被冻结)?

2 个答案:

答案 0 :(得分:11)

编辑:我的原始答案不会从任意线程打印出来。我已经在崩溃处理程序项目中编写了一个正确的实现:https://github.com/kstenerud/KSCrash

具体来说,这些文件:

得到一些帮助:

你做的是:

  • 创建一个新的机器上下文结构(_STRUCT_MCONTEXT)
  • 使用thread_get_state()
  • 填写其堆栈状态
  • 获取程序计数器(第一个堆栈跟踪条目)和帧指针(所有其余部分)
  • 逐步指向帧指针指向的堆栈帧,并将所有指令地址存储在缓冲区中供以后使用。

请注意,您应该在执行此操作之前暂停线程,否则可能会产生不可预测的结果。

堆栈框架中填充了包含两个指针的结构:

  • 指向堆栈上一级的指针
  • 指示地址

因此,您需要在走框架时考虑到这一点,以填写堆栈跟踪。还有可能堆栈损坏,导致指针坏,这会导致程序崩溃。你可以通过使用vm_read_overwrite()复制内存来解决这个问题,vm_read_overwrite()会首先询问内核是否可以访问内存,因此它不会崩溃。

一旦你有了堆栈跟踪,就可以像往常一样在它上面调用backtrace()(崩溃处理程序必须是异步安全的,所以它实现了自己的backtrace方法,但在正常情况下,backtrace()很好)。

答案 1 :(得分:3)

以下是从另一个线程获取callstack的更安全的方法:Implementationsome background information。它使用信号处理并在目标线程中生成信号处理程序。它的优点还在于它比您的解决方案更具跨平台性,即它应该适用于<signal.h><execinfo.h>的任何位置。

对于打印,您可以像在自己的建议中一样使用backtrace_symbols。但是您可能对实现here的扩展版本感兴趣。它使用libbfd(来自binutils;最新版本也主要适用于MacOSX,请参阅here以获取可能与您无关的小限制)来读取调试信息并添加行号和其他信息(如果所有其他信息都失败,它也会回退到dladdr;这就是backtrace_symbols正在做的事情。

相关问题