segvを取得するときにコードを実行するには、まずSIGSEGVをトラップする必要があります。これはposixコードなので、類似のものがアンドロイドで動作するはずです:
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の最初のものとしてそれをすることができますが、mainまでスタックトレースを取得しません。それらを前もって必要とする場合は、グローバルオブジェクトのコンストラクタからこの関数を呼び出すことができます。しかし、それが最初に呼ばれるコンストラクタであるという保証はありません。それが早期に呼び出されることを確認する方法があります。たとえば、オーバーロード演算子new - デバッグビルド - では、最初の割り当て時にスタックトレースを初期化し、次に実演算子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 –