您需要首先捕获SIGSEGV以在您获得segv时执行代码。这是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 - 在调试版本中 - 首先在第一次分配时初始化堆栈跟踪,然后调用新的真实运算符。这会给你从第一次分配开始的堆栈跟踪。
要打印堆栈跟踪:
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。当然用-g和与-rdynamic链接。
检查答案。这是专门为Android http://stackoverflow.com/a/28858941/365229 –