【问题标题】:Printing a stack trace from another thread从另一个线程打印堆栈跟踪
【发布时间】:2011-01-22 00:06:33
【问题描述】:

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

【问题讨论】:

    标签: iphone objective-c stack-trace


    【解决方案1】:

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

    具体来说,这些文件:

    在以下方面的帮助下:

    你要做的是:

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

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

    堆栈帧被包含两个指针的结构填充:

    • 指向堆栈上一层的指针
    • 指令地址

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

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

    【讨论】:

    • 请注意,您应该在读取堆栈时暂停线程。
    • 另外,你确定这行得通吗?它使用__builtin_frame_address,它始终与 current 线程有关。
    • 所以事实证明这实际上不起作用(它确实打印了堆栈跟踪,但我没有意识到它是从当前线程打印的)。我有一些新代码可以按预期工作,但还没有准备好发布。准备好后我会发布更新。
    • 嗨!关于这个主题的任何消息?谢谢。
    • 这些文件似乎不存在于更高版本的存储库中。我试图实现类似的目标(stackoverflow.com/questions/41298259/…)。我可以按原样使用你的框架吗?
    【解决方案2】:

    这是从另一个线程获取调用堆栈的一些更安全的方法:Implementationsome background information。它使用信号处理并在目标线程中产生一个信号处理程序。它还具有比您的解决方案更跨平台的优势,即它应该可以在您拥有<signal.h><execinfo.h> 的任何地方工作。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-09-08
      • 2015-07-27
      • 1970-01-01
      • 2020-07-25
      • 2018-07-06
      • 2013-09-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多