Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/164.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Android NDK上获取堆栈跟踪_Android_C++_Linux_Android Ndk_Stack Trace - Fatal编程技术网

在Android NDK上获取堆栈跟踪

在Android NDK上获取堆栈跟踪,android,c++,linux,android-ndk,stack-trace,Android,C++,Linux,Android Ndk,Stack Trace,首先:这个问题已经被问了好几次,一些答案很有用,但没有一个能提供有效的解决方案。 我开始尝试的代码从。令人惊讶的是,它确实做到了这一点,但存在一个巨大的问题:我能想到的调用此代码的唯一方法是SIGSEGVhandler,它有自己的堆栈-因此我无法像那样获得崩溃应用程序的实际堆栈 然后,我试着合并。它稍微好一点——它产生堆栈的第一项(崩溃发生的方法)。但这是在-没有实际的回溯。因此,一旦崩溃发生在第三方库(或标准库)中,这些信息就毫无意义 我如何进一步改进代码,并最终获得我可怜的崩溃应用程序的堆栈

首先:这个问题已经被问了好几次,一些答案很有用,但没有一个能提供有效的解决方案。 我开始尝试的代码从。令人惊讶的是,它确实做到了这一点,但存在一个巨大的问题:我能想到的调用此代码的唯一方法是
SIGSEGV
handler,它有自己的堆栈-因此我无法像那样获得崩溃应用程序的实际堆栈

然后,我试着合并。它稍微好一点——它产生堆栈的第一项(崩溃发生的方法)。但这是在-没有实际的回溯。因此,一旦崩溃发生在第三方库(或标准库)中,这些信息就毫无意义

我如何进一步改进代码,并最终获得我可怜的崩溃应用程序的堆栈跟踪

p.S.在安卓4.0.3和安卓5.0上测试,到目前为止,行为是相同的。我希望至少支持5.0和最近的早期版本,如4.3-4.4。

您尝试过该库吗

它是一个JNI信号捕捉器,允许将SIGSEGV(+)信号转换为java异常,并混合使用JNI/java回溯。它可以使用API-19,但我还没有机会在API>19上测试它。它提供可以传递给addr2line的程序地址,以便获得对源的最终引用

代码模板:

#include "coffeejni.h"
#include "coffeecatch.h"

void   MyClass::foo(JNIEnv *env, int arg1, int arg2) {
    ....
    int  rc;
    COFFEE_TRY_JNI(env, rc = crashInside(arg1, arg2));
    ....
}
跟踪的示例:

F/myapp   (24535): "DESIGN ERROR": thread=t1
F/myapp   (24535): java.lang.Error: signal 11 (Address not mapped to object) at address 0xdeadbaad [at libc.so:0x18282]
F/myapp   (24535):  at com.example.NativeSupport.nsc(Native Method)
F/myapp   (24535):  at com.example.NativeSupport.nsc_quiet(NativeSupport.java:328)
F/myapp   (24535):  at com.example.NativeSupport.loop(NativeSupport.java:287)
F/myapp   (24535):  at com.example.NativeSupport.access$2(NativeSupport.java:274)
F/myapp   (24535):  at com.example.NativeSupport$2.run(NativeSupport.java:124)
F/myapp   (24535):  at java.lang.Thread.run(Thread.java:856)
F/myapp   (24535): Caused by: java.lang.Error: signal 11 (Address not mapped to object) at address 0xdeadbaad [at libc.so:0x18282]
F/myapp   (24535):  at system.lib.libc_so.0x18282(Native Method)
F/myapp   (24535):  at system.lib.libc_so.0xdc04(abort:0x4:0)
F/myapp   (24535):  at data.data.example.lib.libexample_so.0xf147(Native Method)
F/myapp   (24535):  at data.data.example.lib.libexample_so.0x12d1b(Native Method)
F/myapp   (24535):  at data.data.example.lib.libexample_so.0x1347b(Native Method)
F/myapp   (24535):  at data.data.example.lib.libexample_so.0x13969(Native Method)
F/myapp   (24535):  at data.data.example.lib.libexample_so.0x13ab3(Native Method)
F/myapp   (24535):  at data.data.example.lib.libexample_so.0x17a9b(Native Method)
F/myapp   (24535):  at system.lib.libdvm_so.0x1f4b0(dvmPlatformInvoke:0x70:0)
F/myapp   (24535):  at system.lib.libdvm_so.0x4dfa5(dvmCallJNIMethod(unsigned int const*, JValue*, Method const*, Thread*):0x164:0)
F/myapp   (24535):  at system.lib.libdvm_so.0x28920(Native Method)
F/myapp   (24535):  at system.lib.libdvm_so.0x2d0b0(dvmInterpret(Thread*, Method const*, JValue*):0xb4:0)
F/myapp   (24535):  at system.lib.libdvm_so.0x5f599(dvmCallMethodV(Thread*, Method const*, Object*, bool, JValue*, std::__va_list):0x110:0)
F/myapp   (24535):  at system.lib.libdvm_so.0x5f5c3(dvmCallMethod(Thread*, Method const*, Object*, JValue*, ...):0x14:0)
F/myapp   (24535):  at system.lib.libdvm_so.0x549eb(Native Method)
F/myapp   (24535):  at system.lib.libc_so.0x12dd0(__thread_entry:0x30:0)
F/myapp   (24535):  at system.lib.libc_so.0x12534(pthread_create:0xac:0)
堆栈跟踪的本机(jni)部分是:

F/myapp   (24535):  at data.data.example.lib.libexample_so.0xf147(Native Method)
F/myapp   (24535):  at data.data.example.lib.libexample_so.0x12d1b(Native Method)
F/myapp   (24535):  at data.data.example.lib.libexample_so.0x1347b(Native Method)
F/myapp   (24535):  at data.data.example.lib.libexample_so.0x13969(Native Method)
F/myapp   (24535):  at data.data.example.lib.libexample_so.0x13ab3(Native Method)
F/myapp   (24535):  at data.data.example.lib.libexample_so.0x17a9b(Native Method)
最后得到一个仿人可读的回溯:

cd android-ndk/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64/bin
./arm-linux-androideabi-addr2line -e /home/joe/myproj/obj/local/armeabi-v7a/libexample.so 0xf147 0x12d1b 0x1347b 0x13969 0x13ab3 0x17a9b

需要明确的是:您正试图编写一个应用程序内崩溃处理程序来捕获失败后的堆栈跟踪?除非使用了
sigaltstack
,否则信号处理程序没有自己的堆栈,尽管堆栈展开器可能不知道如何跨过信号堆栈帧。你的最终目标是什么?NDK的ACRA?@fadden:对,我想得到一个死后的堆栈跟踪。它看起来像是信号处理程序有自己的堆栈,它起源于
art::handleFault
或类似的东西(在5.0上)。什么是ACRA?我听说有传言说ART提供了自己的信号处理器,该处理器与前一个处理器相连;如果是这样的话,您将看到Dalvik在5.0和4.x上的不同行为。它位于系统安装的信号处理程序之上,该处理程序为debuggerd系统处理程序提供信息(在本机崩溃后,该处理程序将堆栈跟踪输出到日志文件)。我不认为Android pthread lib使用的是
sigaltstack
,但我已经有一段时间没有检查过了。您需要将SP从信号帧中挖出,并将其用作您的释放点,而不是当前SP。@fadden:谢谢。我相信我可以得到SP,但我不知道从哪里获得它——到目前为止,我发现的代码只显式地接受PC并使用它进行API调用。从
ucontext
中取出PC有帮助,但效果不太好。您可以使用中的一些内容(注意
Unwind
in取出ucontext)。我不知道这些东西有没有在NDK上发表过。我试过了,但没能做到我想要的。但我也没有找到获取堆栈的方法(无论是地址还是符号)。它在Coffecatch API中吗?您有任何示例代码吗?此外,这些地址是否与
dladdr
兼容?请参阅上面我更改的答案+请确保您使用的是git的最新版本,旧版本不适用于现代ndk。谢谢。我已经看到它可以抛出带有某种堆栈跟踪的Java异常,但是我需要
COFFEE\u CATCH
块中的那些地址,修改coffecatch源代码以访问该地址列表有多难?此外,必须将每个方法包装在
try/catch
中是一个很大的障碍。我有数百个(当然超过100个)本机方法,每个都必须修改。一个全局信号处理器是非常方便的。。。如果你想从内部信号处理器中转储回溯,这将是一项巨大的重构工作(咖啡源只能作为参考设计示例来帮助你),我估计需要2-4天。下一种方法是复制静态缓冲区中的信号上下文(cofeecatch将其复制到特殊的“catch”位置),然后将其转储到默认线程内。setDefaultUncaughtExceptionHandler(..)处理程序。但是,只要您必须为所有线程设置信号处理程序,就可以简单地使用COFFEE\u CATCH块线程的“main”函数进行包装。好的,假设我坚持正常的coffeecatch结构-在每个本机方法中尝试CATCH。我只希望调用堆栈位于
catch
块中,并且不与Java交互。这有多难?