问题描述
我知道我可以使用backtrace()或[NSThread callStackSymbols]来获取当前线程的堆栈跟踪,但是如何获取不同线程的堆栈跟踪(假设它已冻结)?
I know I can get the stack trace of the current thread using backtrace() or [NSThread callStackSymbols], but how would I get at the stack trace of a DIFFERENT thread (assuming it's been frozen)?
推荐答案
我的原始答案不会从任意线程打印.此后,我在崩溃处理程序项目中编写了正确的实现: https://github.com/kstenerud/KSCrash
My original answer will not print from an arbitrary thread. I've since written a proper implementation in my crash handler project: https://github.com/kstenerud/KSCrash
具体来说,这些文件:
- https://github.com/kstenerud/KSCrash/blob/master/KSCrash/KSCrash/Reporting/Tools/KSBacktrace.h
- https://github.com/kstenerud/KSCrash/blob/master/KSCrash/KSCrash/Reporting/Tools/KSBacktrace.c
- https://github.com/kstenerud/KSCrash/blob/master/KSCrash/KSCrash/Reporting/Tools/KSBacktrace.h
- https://github.com/kstenerud/KSCrash/blob/master/KSCrash/KSCrash/Reporting/Tools/KSBacktrace.c
在以下方面的帮助下:
- https://github.com/kstenerud/KSCrash/blob/master/KSCrash/KSCrash/Reporting/Tools/KSMach.h
- https://github.com/kstenerud/KSCrash/blob/master/KSCrash/KSCrash/Reporting/Tools/KSMach.c
- https://github.com/kstenerud/KSCrash/blob/master/KSCrash/KSCrash/Reporting/Tools/KSMach.h
- https://github.com/kstenerud/KSCrash/blob/master/KSCrash/KSCrash/Reporting/Tools/KSMach.c
您要做的是:
- 创建新的计算机上下文结构(_STRUCT_MCONTEXT)
- 使用thread_get_state()填充其堆栈状态
- 获取程序计数器(第一个堆栈跟踪条目)和帧指针(其余所有帧)
- 逐步遍历帧指针所指向的堆栈帧,并将所有指令地址存储在缓冲区中以备后用.
请注意,您应该在执行此操作之前先暂停线程,否则可能会导致无法预料的结果.
Note that you should pause the thread before doing this or else you can get unpredictable results.
堆栈框架填充了包含两个指针的结构:
The stack frame is filled with structures containing two pointers:
- 指向堆栈中的下一个级别
- 说明地址
因此,在遍历框架以填充堆栈跟踪时需要考虑到这一点.还有可能发生堆栈损坏,导致指针错误,从而使程序崩溃的情况.您可以通过使用vm_read_overwrite()复制内存来解决此问题,它首先询问内核是否有权访问内存,因此不会崩溃.
So you need to take that into account when walking the frame to fill out your stack trace. There's also the possibility of a corrupted stack, leading to a bad pointer, which will crash your program. You can get around this by copying memory using vm_read_overwrite(), which first asks the kernel if it has access to the memory, so it doesn't crash.
一旦有了堆栈跟踪,就可以像正常情况一样在其上调用backtrace()(崩溃处理程序必须是异步安全的,因此它可以实现自己的backtrace方法,但在正常情况下,backtrace()可以).
Once you have the stack trace, you can just call backtrace() on it like normal (The crash handler has to be async-safe so it implements its own backtrace method, but in normal cases backtrace() is fine).
这篇关于从另一个线程打印堆栈跟踪的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!