5

奇妙なエラーがあり、どこから来たのかわかりません。logcatに表示されるのは:

01-10 17:07:10.665: A/libc(20449): Fatal signal 11 (SIGSEGV) at 0x00000000 (code=1)

アプリを実行してもすぐにはこのエラーは発生しません。ランダムな時間(1分から5分の間)の後に発生します。このエラーを再現することはできません。ランダムに見えます。他に情報がないため、デバッグが困難です。ライブラリにログ情報を追加しようとしましたが、クラッシュが発生した場所がわかりません。

同じアプリをx回実行し、異なるSIGSEGVアドレスを取得しました(以前と同じアドレスである場合もあります:

01-10 17:29:04.650: A/libc(21588): Fatal signal 11 (SIGSEGV) at 0x6c707063 (code=1)

01-10 17:25:55.165: A/libc(21473): Fatal signal 11 (SIGSEGV) at 0x0069004c (code=1)

01-10 17:11:58.780: A/libc(20742): Fatal signal 11 (SIGSEGV) at 0x00000000 (code=1)

01-10 17:00:02.010: A/libc(20160): Fatal signal 11 (SIGSEGV) at 0x00000018 (code=1)

私のアプリは、サーバーから更新を受信するNetworkThreadを持つc++ライブラリを使用しています。Java側には、NetworkThreadからの新しい更新があるかどうかをチェックするWorkerThreadがあり、新しい更新がある場合は、すべてのリスナーに通知します。また、ロケーションが更新されたときにいくつかのJNI呼び出しを行うLocationSpotter(Java側)もあります。

これをデバッグする方法、またはSIGSEGVから取得したアドレスを使用してアプリをデバッグする方法はありますか?また、現在のJNIEnvを取得する(そしてAttachCurrentThreadを呼び出す)いくつかのメソッドに共有JavaVMオブジェクトを使用しています。そのスレッドは安全ですか?

SIGSEGVエラーが発生した後(アプリが実際にクラッシュする前)、NetworkThreadから更新を受信して​​いることに気付きました。これは、NetworkThreadがおそらく機能していることを意味します。

また、SIGSEGVの前に出力された最後のメッセージが "notifyAll1"であるため、(notifyAllメソッドで)問題の原因となる可能性のある行に気づきました。

for (unsigned i = 0; i < listeners.size(); i++) {
    try {
        __android_log_print(ANDROID_LOG_INFO, "FROM C++", "notifyAll1");
        if (listeners.at(i) == NULL)
            __android_log_print(ANDROID_LOG_INFO, "FROM C++", "LISTENER NULL");


        listeners.at(i)->update(u); // <- This line is a potential suspect
        __android_log_print(ANDROID_LOG_INFO, "FROM C++", "notifyAll2");

logcat:

01-10 17:07:10.665: I/FROM C++(20449): notifyAll1
01-10 17:07:10.665: A/libc(20449): Fatal signal 11 (SIGSEGV) at 0x00000000 (code=1)

次に、各リスナーのメソッドの最初の行にログを印刷しようとしましたupdateが、どれも印刷されませんでした(これは本当に奇妙だと思います)。

どんな助けでも大歓迎です

4

3 に答える 3

1

次のようにnotifyAllループを書き直す必要があると思います。

for (unsigned i = 0; i < listeners.size(); i++) {
  try {
    __android_log_print(ANDROID_LOG_INFO, "FROM C++", "notifyAll1 i=%u", i);
    auto listener = *listeners.at(i);

    if (&listener == NULL) {
      __android_log_print(ANDROID_LOG_INFO, "FROM C++", "LISTENER NULL");
    }
    else {
      __android_log_print(ANDROID_LOG_INFO, "FROM C++", "notifyAll2 : listener[%u] at %p", i, &listener);
      listener.update(u);
    }
  • 元のコードでは、チェックはログに出力するだけでしたが、update()はまだ失敗します( @Robinはこれに気付きました)
  • 元のコードでは、 check とupdate()の間でリスナーが無効化された NULL を取得する可能性があります
  • 上記の変更後でも、listeners.at(i)が指すリスナー オブジェクトが無効になるとupdate()がクラッシュする可能性があります。

ただし、例外処理が原因でクラッシュが発生する可能性があります。あなたはcatch(...)コードを明らかにしなかったので、これについて話すことはできません。

于 2013-12-29T12:37:59.800 に答える