您需要首先捕獲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 –