【发布时间】:2011-01-22 00:06:33
【问题描述】:
我知道我可以使用 backtrace() 或 [NSThread callStackSymbols] 获取当前线程的堆栈跟踪,但是如何获取不同线程的堆栈跟踪(假设它已被冻结)?
【问题讨论】:
标签: iphone objective-c stack-trace
我知道我可以使用 backtrace() 或 [NSThread callStackSymbols] 获取当前线程的堆栈跟踪,但是如何获取不同线程的堆栈跟踪(假设它已被冻结)?
【问题讨论】:
标签: iphone objective-c stack-trace
编辑:我的原始答案不会从任意线程打印。我已经在我的崩溃处理程序项目中编写了一个正确的实现:https://github.com/kstenerud/KSCrash
具体来说,这些文件:
在以下方面的帮助下:
你要做的是:
请注意,在执行此操作之前您应该暂停线程,否则您会得到不可预知的结果。
堆栈帧被包含两个指针的结构填充:
因此,在遍历帧以填写堆栈跟踪时,您需要考虑到这一点。还有可能是堆栈损坏,导致指针错误,这会使您的程序崩溃。你可以通过使用 vm_read_overwrite() 复制内存来解决这个问题,它首先询问内核是否可以访问内存,因此它不会崩溃。
一旦你有了堆栈跟踪,你可以像往常一样调用 backtrace() (崩溃处理程序必须是异步安全的,所以它实现了自己的 backtrace 方法,但在正常情况下 backtrace() 很好)。
【讨论】:
__builtin_frame_address,它始终与 current 线程有关。
这是从另一个线程获取调用堆栈的一些更安全的方法:Implementation 和 some background information。它使用信号处理并在目标线程中产生一个信号处理程序。它还具有比您的解决方案更跨平台的优势,即它应该可以在您拥有<signal.h> 和<execinfo.h> 的任何地方工作。
对于打印,您可以使用backtrace_symbols,就像您在自己的建议中所做的那样。但是您可能对实现 here 的扩展版本感兴趣。它使用 libbfd(来自binutils;最近的版本也主要适用于 MacOSX,请参阅here 了解可能与您无关的小限制)来读取调试信息并添加行号和其他信息(它如果一切都失败了,也会退回到dladdr;这就是backtrace_symbols正在做的事情。
【讨论】: