Неверный адрес кучи и фатальный сигнал 11

Время от времени мое приложение будет падать, и мой журнал будет читать:

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

Иногда code=2, но всегда Fatal signal 11 и invalid 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);
}

Несмотря на то, что я пытался исследовать, что с этим происходит, я все еще теряюсь, когда дело доходит до исправления. Если у кого-то есть какое-то понимание, я определенно был бы признателен за его просмотр. Ошибка не выдается каждый раз, когда я execute AsyncTasks, но я не могу найти большую часть шаблона, который помог бы определить, почему это происходит. На SO есть несколько других тем о fatal signal 11, но в моем случае они не очень помогают.


person adneal    schedule 19.05.2012    source источник
comment
Есть ли в вашем приложении JNI?   -  person Julie in Austin    schedule 19.05.2012
comment
У меня есть JNI в моем приложении, и я получаю эту ошибку. Любые предложения, @JulieinAustin   -  person Whitney Imura    schedule 18.02.2014
comment
@WhitneyImura В этом вопросе обсуждается, что делать, когда JNI вызывает эту ошибку.   -  person Kevin    schedule 26.06.2014


Ответы (2)


Я только что столкнулся с той же проблемой и имел ее в воспроизводимом состоянии. Это ошибка, которую я получал:

08-04 17:37:05.491: A/libc(4233): @@@ ПРЕРЫВАНИЕ: НЕВЕРНЫЙ АДРЕС КУЧИ В dlfree (код=1)

Все сводилось к тому, что вызов функции выполнялся из двух разных потоков одновременно.

В частности, эта функция была методом close() BluetoothSocket.

Я проверил исходный код на этом веб-сайте , и вызов не синхронизирован (не уверен, что это изменилось, так как это из Android 2.1).

В любом случае, может быть, у вас есть подобный сценарий, когда вызов функции выполняется из нескольких потоков? Не могу сказать наверняка из исходного кода, который вы показываете.

Также вы пытались не использовать THREAD_POOL_EXECUTOR? Согласно руководству для разработчиков Android:

При первом появлении AsyncTasks выполнялись последовательно в одном фоновом потоке. Начиная с DONUT, это было изменено на пул потоков, позволяющий нескольким задачам работать параллельно. Начиная с HONEYCOMB, задачи выполняются в одном потоке, чтобы избежать распространенных ошибок приложений, вызванных параллельным выполнением.

person Ivan    schedule 04.08.2012
comment
как вы узнали, что метод, вызывающий ваши проблемы, был методом close () BluetoothSocket? - person bonifaz; 04.10.2012
comment
Я изучил код и заметил, что вызываю метод close() из двух разных потоков, вероятно, почти одновременно. - person Ivan; 06.10.2012
comment
Этот ответ абсолютно правильный. У меня был тот же код ошибки (@@@ ABORTING: LIBC: ARGUMENT IS INVALID HEAP ADDRESS IN dlfree addr). В моем конкретном случае у меня было два разных потока, вызывающих метод PathMeasure.getPosTan. После того, как я изменил свой код, чтобы гарантировать, что это будет вызываться только одним потоком за раз, ошибка исчезла. - person Luis; 14.03.2013
comment
Вау, это правда, я тоже использую bluetooth.close() хе-хе. Проблема решается за секунды! - person Salvatorelab; 20.05.2013
comment
Похоже, они изменили реализацию BluetoothSocket.close в 4.2. - person snak; 09.07.2013
comment
Это может помочь другим, но моя проблема заключалась в том, что я вызывал Canvas.drawLine() (на совершенно другом холсте / растровых изображениях) в отдельных потоках. И в редких случаях доступ к методу (с использованием внутреннего кода C для рисования?) происходил в одно и то же время и приводил к сбою. - person IAmGroot; 01.04.2016
comment
Я могу решить свою проблему, используя это, но возникает еще одна проблема. Мое представление зависает, когда я использую THREAD_POOL_EXECUTOR или синхронизированный метод. что мне теперь делать? любая идея, пожалуйста... - person Priyanka; 08.08.2019

У меня была такая же ошибка вчера. Так было всегда, но не всегда последовательно. Что вызвало это для меня, до сих пор не упоминалось.

Я думал, что у меня может быть похожая проблема, потому что я тоже имел дело с потоками, однако я удалил все свои потоки, и проблема все еще возникала. Наконец, после множества операторов печати я смог отследить его до класса, который я создал экземпляром, который имел указатель в качестве частного члена, но я забыл инициализировать указатель.

Позже, когда этот класс разрушился, он пытался удалить указатель, однако, поскольку указатель не был инициализирован в 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 побеждает, помогая мне отслеживать ошибки, поскольку он кажется более разборчивым.

person PolyMesh    schedule 13.06.2013
comment
Почему минус? Я не понимаю, почему убедиться, что указатели инициализированы, — это плохо, особенно когда это также вызывает рассматриваемую ошибку. - person PolyMesh; 20.07.2013