3

私の Android アプリ (Java+NDK) は、0xdeadd00d によって引き起こされた多くのクラッシュ (シグナル) を報告します。Dalvik VM abort の省略形であることはよく知られています。私の JNI 呼び出し内ではこれらは発生しませんが、シグナル処理はネイティブ環境で行われます。しかし、ネイティブ クラッシュ レポートが通常報告するもの (レジスタ、スタック) は、それらのデバッグには役に立ちません。

ネイティブ シグナル ハンドラから Java コール スタックにアクセスする方法はありますか? または、最近の logcat アクティビティの一部をダンプしますか?

4

1 に答える 1

0

解決策: シグナル ハンドラに deadd00d の特別な条件を導入します。logcat の最後の 1024 バイトを読み取り、クラッシュ ログに詰め込みます。

これでまともな診断ができます。

//n is the length of the file tail to read
//Returns # of byte read
size_t ReadLogcat(char *Buf, size_t n)
{
    char s[sizeof(s_DataPath) + 30];
    //s_DataPath contains the result of Context.getDir("Data")

    strcpy(s, "logcat -d -f ");
    char *fn = s + strlen(s);
    strcat(s, s_DataPath);
    strcat(s, "/logcat"); //Temp file for the logcat
    size_t r = 0;
    system(s); //Dump the snapshot of the logcat into the file called logcat
    FILE *f = fopen(fn, "r");
    if(f)
    {
        fseek(f, -n, SEEK_END); //We need the end of the file
        r = fread(Buf, 1, n, f);
        fclose(f);
    }
    unlink(fn); //Don't need the logcat file anymore
    return r;
}

static void DumpLogcat(FILE *f)
{
    char Buf[1024];
    size_t r;
    if(r = ReadLogcat(Buf, sizeof(Buf)))
    {
        fputs("\nLogcat:\n", f);
        fwrite(Buf, 1, r, f);
    }
}

void OnSignal(int signal, siginfo_t *si, void *p)
{
    FILE *f = OpenCrashLog(); //opens a file in the data dir; details are irrelevant

    //Lots of data dumping here... Version, stack, registers, etc.
    //...

    if((unsigned)si->si_addr == 0xdeadd00d) //Try and dump some Logcat
        DumpLogcat(f);
}
于 2013-11-14T17:11:30.533 に答える