Невалиден адрес на купчина и фатален сигнал 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 08-04 17:37:05.491: A/libc(4233): Фатален сигнал 11 (SIGSEGV) при 0xdeadbaad (код=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