我写了一段代码,以便测试ndk-stack 这是代码片段
libtest.so
std::vector<int> testVec;
testVec.at(500);
但我得到的是不完整的堆栈
********** Crash dump: **********
Build fingerprint: 'MI/casablanca_icntv/casablanca:4.2.2/CADEV/1253:user/release-keys'
pid: 24989, tid: 24989 >>> com.ktcp.video <<<
signal 11 (SIGSEGV), fault addr deadbaad
Stack frame #00 pc 0001a852 /system/lib/libc.so: Routine ????:0
Stack frame #01 pc 00018190 /system/lib/libc.so (abort): Routine ????:0
Stack frame #00 pc 0001a852 /system/lib/libc.so: Routine ????:0
Stack frame #01 pc 00018190 /system/lib/libc.so (abort): Routine ????:0
Stack frame #00 pc 0001a852 /system/lib/libc.so: Routine ????:0
Stack frame #01 pc 00018190 /system/lib/libc.so (abort): Routine ????:0
Stack frame #00 pc 0001a852 /system/lib/libc.so: Routine ????:0
Stack frame #01 pc 00018190 /system/lib/libc.so (abort): Routine ????:0
^C^C
在堆栈中没有看到我的代码,不完整的堆栈
如何修复
答案 0 :(得分:1)
0xdeadbaad
表示故意中止。你可以在你得到的堆栈片段上看到对abort()
的调用。我猜你是在触发一个断言失败(会出现在logcat中)。
在某些版本的Android上,在某些情况下,您无法从abort()
获得良好的跟踪。问题的一部分是该函数被noreturn
属性标记,因此当您执行以下操作时,编译器不会吐出投诉:
int foo(int x) {
if (x == 0) {
return 12345;
} else {
abort();
}
}
如果返回abort()
,则此方法将返回未定义的值。在ARM上,返回地址存在于LR寄存器中,并在必要时保留在堆栈中......但如果函数没有返回,则不需要保存返回地址,因此允许编译器抛出它远。这很好,直到你想拥有堆栈跟踪的地址。如果重新使用LR,并且旧值没有溢出到堆栈,它就会消失。
我认为可能存在修复编译器问题的版本,但某些汇编器元数据错误,导致类似的问题。
Android的最新版本不应出现此行为。最新版本还使用更传统的SIGABRT替换了0xdeadbaad
的访问权限,因此您不再看到此特定崩溃签名。
(FWIW,您可以看到noreturn
in 4.2.2 (see comments)的尝试解决方法。它在早期版本的系统中有效。)
答案 1 :(得分:0)
它说signal 11 (SIGSEGV), fault addr deadbaad
,其中0xDeadBaad
(死,坏)很可能默认存储到未初始化的内存中(这是一个旧的双关语)。所以它试图读取或执行未初始化的内存。