如何在Android上的故障转储中获得更多的调用堆栈深度?

时间:2015-06-01 18:01:24

标签: android c++ android-ndk crash crash-dumps

我在C ++中有一些使用NDK的代码。当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级调用堆栈深度的例子。

1 个答案:

答案 0 :(得分:0)

在过去几年中演变的回溯机制显示了能够找到的帧数(最多固定限制为32,IIRC)。如果有什么东西阻止它在堆栈中走得更远,它会提前停止。

ARM上的调用机制将返回地址放在链接寄存器(LR)中,但允许编译器将其溢出到堆栈中。对于“noreturn”功能,它在技术上根本不需要设置它。有一些汇编伪操作可以添加元数据,帮助unwinders找出返回地址的位置,以及最新版本的Android应该都可以工作。

当你得到一个双深的堆栈跟踪时,这意味着当前方法的展开失败,并且它只能显示程序计数器(PC)的值和恰好在LR中的值。 / p>

确保使用-g进行编译以启用调试。

是否直接从JNI调用失败函数?在一些旧版本的Android中,由于代码的结构方式,跟踪将停留在JNI调用桥上,尽管这已在Dalvik back in 2011中修复。然而,最近的设备使用Art,我期望它有不同的做事方式。

类似问题here