我在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级调用堆栈深度的例子。
答案 0 :(得分:0)
在过去几年中演变的回溯机制显示了能够找到的帧数(最多固定限制为32,IIRC)。如果有什么东西阻止它在堆栈中走得更远,它会提前停止。
ARM上的调用机制将返回地址放在链接寄存器(LR)中,但允许编译器将其溢出到堆栈中。对于“noreturn”功能,它在技术上根本不需要设置它。有一些汇编伪操作可以添加元数据,帮助unwinders找出返回地址的位置,以及最新版本的Android应该都可以工作。
当你得到一个双深的堆栈跟踪时,这意味着当前方法的展开失败,并且它只能显示程序计数器(PC)的值和恰好在LR中的值。 / p>
确保使用-g
进行编译以启用调试。
是否直接从JNI调用失败函数?在一些旧版本的Android中,由于代码的结构方式,跟踪将停留在JNI调用桥上,尽管这已在Dalvik back in 2011中修复。然而,最近的设备使用Art,我期望它有不同的做事方式。
类似问题here。