43

ときどきアプリがクラッシュし、ログに次のように表示されます。

@@@ ABORTING: INVALID HEAP ADDRESS IN dlfree
Fatal signal 11 (SIGSEGV) at 0xdeadbaad (code=1)

時々、code=2しかし常に。Fatal signal 11invalid heap address

これが何を意味し、どのように修正するかを調査してみました。このスレッドが最も役に立ちました。しかし、私はまだ解決策がありません。

AsyncTasksいくつかのイメージをダウンロードするためにいくつかを実行すると、エラーが発生します。

これが私のメインですAsyncTask

public class FetchArtistImages extends AsyncTask<Void, Integer, String[]> implements Constants {

private final WeakReference<Context> contextReference;

public FetchArtistImages(Context context) {
    contextReference = new WeakReference<Context>(context);
}

@Override
protected String[] doInBackground(Void... params) {
    String[] projection = new String[] {
            Audio.Artists._ID, Audio.Artists.ARTIST
    };
    String sortOrder = Audio.Artists.DEFAULT_SORT_ORDER;
    Uri uri = Audio.Artists.EXTERNAL_CONTENT_URI;
    Cursor c = contextReference.get().getContentResolver()
            .query(uri, projection, null, null, sortOrder);
    ArrayList<String> artistIds = new ArrayList<String>();
    if (c != null) {
        int count = c.getCount();
        if (count > 0) {
            final int ARTIST_IDX = c.getColumnIndex(Audio.Artists.ARTIST);
            for (int i = 0; i < count; i++) {
                c.moveToPosition(i);
                artistIds.add(c.getString(ARTIST_IDX));
            }
        }
        c.close();
        c = null;
    }
    return artistIds.toArray(new String[artistIds.size()]);
}

@Override
protected void onPostExecute(String[] result) {
    for (int i = 0; i < result.length; i++) {
            new LastfmGetArtistImages(contextReference.get()).executeOnExecutor(
                    AsyncTask.THREAD_POOL_EXECUTOR, result[i]);
    }
    super.onPostExecute(result);
}

これがどうなっているのかを調べてみましたが、修正に関してはまだ迷っています。誰かが何らかの洞察を持っているなら、私はそれを見ていただければ幸いです。毎回エラーがスローされるわけではありませんがexecuteAsyncTasksこれが発生している理由を特定するのに役立つパターンがあまり見つかりません。SO に関する他のスレッドがいくつかありますがfatal signal 11、私の場合はあまり役に立ちません。

4

2 に答える 2

44

同じ問題に遭遇し、再現可能な状態になりました。これは私が得ていたエラーです:

08-04 17:37:05.491: A/libc(4233): @@@ 中止: dlfree 08-04 17:37:05.491 の無効なヒープ アドレス: A/libc(4233): 0xdeadbaad で致命的なシグナル 11 (SIGSEGV) (コード=1)

つまり、2 つの異なるスレッドから同時に関数呼び出しが行われるということです。

具体的には、この関数は BluetoothSocket の close() メソッドでした。

このWebサイトでソースコードを確認しましたが、呼び出しが同期されていません(Android 2.1から変更されたかどうかはわかりません)。

いずれにせよ、関数呼び出しが複数のスレッドから行われる同様のシナリオはありますか? あなたが示しているソースコードからは確かに言えません。

また、THREAD_POOL_EXECUTOR を使用しないようにしましたか? アンドロイド開発ガイドによると:

最初に導入されたとき、AsyncTasks は単一のバックグラウンド スレッドでシリアルに実行されました。DONUT 以降、これはスレッドのプールに変更され、複数のタスクが並行して動作できるようになりました。HONEYCOMB 以降、並列実行によって発生する一般的なアプリケーション エラーを回避するために、タスクは単一のスレッドで実行されます。

于 2012-08-04T23:10:02.433 に答える
8

昨日、同じエラーが発生しました。それは常に起こりましたが、常に一貫しているとは限りません。何が私にそれを引き起こしたのか、これまでのところ言及されていません。

私もスレッドを扱っていたので、同様の問題があるのではないかと思いましたが、すべてのスレッドを削除しても問題は引き続き発生していました。最後に、一連の print ステートメントの後、プライベート メンバーとしてポインターを持つインスタンス化したクラスまで追跡できましたが、ポインターを初期化するのを忘れていました。

後でそのクラスが破棄されたときにポインターを削除しようとしましたが、ポインターが NULL に初期化されていなかったため、ガベージ値がある場合とない場合があるため、クラッシュが発生しない場合と発生する場合があります。おそらく、ガベージ値が自分に属していないメモリの場所であった場合、またはガベージ値があり、重要なものを削除した場合に、クラッシュ/エラーが発生するためです。

これは、私が遭遇した問題の簡略化された例です。

class BadFoo
{
public:
    BadFoo() {} // BAD! We didn't initialize the pointer
    ~BadFoo() {
        if (myPtr) {
            delete myPtr;
        }
    }
    // OTHER MEMBER FUNCTIONS HERE

private:
    int* myPtr;
}

class GoodFoo
{
public:
    GoodFoo() : myPtr(NULL) {} // GOOD! Can't be garbage value now
    ~GoodFoo() {
        if (myPtr) {
            delete myPtr;
        }
    }
    // OTHER MEMBER FUNCTIONS HERE

private:
    int* myPtr;
}

興味深いことに、このクラッシュは Transformer Prime では発生しませんでしたが、Nexus4 では発生しました。複数のデバイスでテストする必要があることを示しています。これまでのところ、Nexus はバグを追跡するのに役立っています。

于 2013-06-13T17:52:17.760 に答える