android - 如何在 Android 上的崩溃转储中获得更多调用堆栈深度?

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

我有一些使用 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/

相关文章:

android - 应用程序签名问题

python - 为什么 Python 递归如此昂贵,我们能做些什么?

c++ - Qt 安装程序框架 : How to sign the maintenancetool. exe

linux - 安装Android-EABI工具链时,是否可以覆盖/usr中的文件?

android - 配置 Sequoyah 调试 JNI 代码

android - 使用 CMake 在 Android Studio 中向 NDK 应用程序添加静态预构建库和 GLESv2 支持

java - 让Android Seekbar线条变细

android - 没有适用于 Flutter Android Studio 项目的 AVD

android - 协程 worker : interrupt doWork() on cancelPendingIntent action

c++ - 如何在开关条件中使用枚举