我有一些使用 NDK 的 C++ 代码。当 C++ 代码(在设备上;而不是通过模拟器)发生崩溃时,我得到一个墓碑(崩溃转储),其中包含一个始终为 2 级深的调用堆栈:
I/DEBUG ( 5089): pid: 5048, tid: 5062 >>> com.example.site <<<
I/DEBUG ( 5089): #00 pc 0059e08c /data/data/com.example.site/lib/libexample.so (_ZNK10MyNamespaceAPI11MyClass12GetDataEv)
I/DEBUG ( 5089): #01 lr 5bc9ef2c /data/data/com.example.site/lib/libexample.so
I/DEBUG ( 5089): 5cc6e764 5bce3070 /data/data/com.example.site/lib/libexample.so
I/DEBUG ( 5089): 5cc6e774 5bce309c /data/data/com.example.site/lib/libexample.so
I/DEBUG ( 5089): 5cc6e784 5bce2af4 /data/data/com.example.site/lib/libexample.so
I/DEBUG ( 5089): 5cc6e788 5c27ea9c /data/data/com.example.site/lib/libexample.so
有没有办法配置我的应用程序或 Android 以在打印到故障转储的调用堆栈中提供更多详细信息和深度?究竟是什么决定了这一点?我见过一些示例,其中人们的调用堆栈深度达到 15 级。
最佳答案
在过去几年中发展起来的回溯机制显示尽可能多的帧(最多固定限制为 32,IIRC)。如果有什么东西阻止它走得更远,它会提前停止。
ARM 上的调用机制将返回地址放在链接寄存器 (LR) 中,但允许编译器将其溢出到堆栈中。对于“noreturn”功能,技术上根本不需要设置它。有一些汇编器伪操作添加了元数据,帮助展开器找出返回地址的位置,并且在更新的 Android 版本中应该都可以。
当你得到一个 two-deep stack trace 时,这意味着在当前方法上展开失败,它只能向你显示程序计数器 (PC) 的值和恰好在 LR 中的值。
确保使用 -g
进行编译以启用调试。
失败的函数是直接从 JNI 调用的吗?在一些旧版本的 Android 中,由于代码的结构方式,跟踪将在 JNI 调用桥停止,尽管这在 Dalvik 中已修复 back in 2011 .不过,最近的设备使用 Art,我希望它有不同的做事方式。
类似问题here .
关于android - 如何在 Android 上的崩溃转储中获得更多调用堆栈深度?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30580147/