Android应用程序崩溃时可以获取C ++堆栈跟踪吗?

在我的C ++代码中发生的大多数错误都会导致应用程序退出,而不输出任何LogCat,也不会在设备上显示消息。 空指针和JNI的不正确使用经常产生这个结果,不用说,它使得debugging非常困难。

目前,我可以在ndk-gdb中使用'bt'命令获取堆栈跟踪信息,但是如果崩溃发生在启动的前2秒钟内,则不会发生崩溃,因为ndk-gdb启动该进程并在启动后附加到该进程。 另外,ndk-gdb是不可靠的,经常说它找不到任何符号,或抱怨非致命的“SIGILL”错误,例如。

有什么办法来捕捉错误,并打印堆栈跟踪,或其他信息时,应用程序崩溃? 例如,如果有一个SIGSEGV,我想知道该应用试图访问哪个地址。

Solutions Collecting From Web of "Android应用程序崩溃时可以获取C ++堆栈跟踪吗?"

trace.txt文件给一些东西? 我不记得他的位置是: /data/anr/trace.txt还是/data/data/{pkg}/trace.txt

当你得到一个segv时,你需要首先捕获SIGSEGV来执行代码。 这是posix代码,所以类似的东西应该在android上工作:

 void abortHandler( int signum, siginfo_t* si, void* unused ) { const char* name = NULL; switch( signum ) { case SIGABRT: name = "SIGABRT"; break; case SIGSEGV: name = "SIGSEGV"; break; case SIGBUS: name = "SIGBUS"; break; case SIGILL: name = "SIGILL"; break; case SIGFPE: name = "SIGFPE"; break; case SIGPIPE: name = "SIGPIPE"; break; } if ( name ) printf( stderr, "Caught signal %d (%s)\n", signum, name ); else printf( stderr, "Caught signal %d\n", signum ); printStackTrace( stderr ); exit( signum ); } void handleCrashes() { struct sigaction sa; sa.sa_flags = SA_SIGINFO; sa.sa_sigaction = abortHandler; sigemptyset( &sa.sa_mask ); sigaction( SIGABRT, &sa, NULL ); sigaction( SIGSEGV, &sa, NULL ); sigaction( SIGBUS, &sa, NULL ); sigaction( SIGILL, &sa, NULL ); sigaction( SIGFPE, &sa, NULL ); sigaction( SIGPIPE, &sa, NULL ); } 

接下来是调用该函数来注册信号处理程序。 你可以把它作为主要的第一件事,但是直到main才会获得堆栈跟踪。 如果以前需要它们,可以从全局对象的构造函数中调用该函数。 但是不能保证它是第一个被调用的构造函数。 有办法确保它被提前调用。 例如,重载操作符new – 在debugging版本中 – 首先初始化第一个分配的堆栈跟踪,然后调用新的真正的操作符。 这会给你从第一次分配开始的堆栈跟踪。

要打印堆栈跟踪:

 void printStackTrace( unsigned int max_frames = 63 ) { void* addrlist[max_frames+1]; // retrieve current stack addresses u32 addrlen = backtrace( addrlist, sizeof( addrlist ) / sizeof( void* )); if ( addrlen == 0 ) { printf( stderr, " <empty, possibly corrupt>\n" ); return; } char** symbollist = backtrace_symbols( addrlist, addrlen ); for ( u32 i = 3; i < addrlen; i++ ) printf( stderr, "%s\n", symbollist[i] ): } 

您将需要做更多的工作来使符号解体以使其可读。 尝试abi :: __ cxa_demangle。 当然用-gbuild立链接与-rdynamic链接。

是的,'execinfo.h'不存在,但CallStack确实:

 #include <utils/CallStack.h> .. CallStack cs; cs.dump(); 

希望它可以帮助这样的信号处理程序。