无效的堆地址和致命信号11

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);
}

尽管我已经尝试研究过这个问题,但当涉及到修复它时,我仍然感到困惑。如果有人有见解,我一定会很感激。错误并不是每次我执行我的异步任务时都会抛出,但我找不到太多模式来帮助隔离为什么会发生这种情况。关于“致命信号11”,SO上有几个其他线程,但在我的情况下它们并没有提供太多帮助。

你的应用程序中有没有使用JNI? - Julie in Austin
我的应用程序中有JNI,并且出现了这个错误。有什么建议吗,@JulieinAustin - Whitney Imura
@WhitneyImura 这个问题 讨论了在JNI引起此错误时应该怎么做。 - Kevin
2个回答

44

我刚遇到了同样的问题,并且处于可以重现的状态。我得到的错误如下:

08-04 17:37:05.491: A/libc(4233): @@@ ABORTING: INVALID HEAP ADDRESS IN dlfree 08-04 17:37:05.491: A/libc(4233): Fatal signal 11 (SIGSEGV) at 0xdeadbaad (code=1)

问题的核心在于两个不同的线程同时调用了同一个函数。

更具体来说,这个函数是 BluetoothSocket 的 close() 方法。

我检查了源代码(该网站),发现该调用未同步(不确定自那时起是否有所改变,因为它来自 Android 2.1)。

无论如何,您是否有类似的场景,即从多个线程中调用同一个函数?从您展示的源代码无法确定。

另外,您是否尝试过不使用 THREAD_POOL_EXECUTOR?根据android dev guide

当首次引入 AsyncTasks 时,它们在单个后台线程上串行执行。从 DONUT 开始,它被更改为一个线程池,允许多个任务并行操作。从 HONEYCOMB 开始,任务在单个线程上执行,以避免由并行执行引起的常见应用程序错误。


你是如何发现导致问题的方法是BluetoothSocket的close()方法的? - bonifaz
这个答案是绝对正确的。我也遇到了相同的错误代码 (@@@ ABORTING: LIBC: ARGUMENT IS INVALID HEAP ADDRESS IN dlfree addr)。在我的情况下,有两个不同的线程调用了PathMeasure.getPosTan方法。当我修改了代码以确保这只会被一个线程调用时,错误消失了。 - Luis
1
哇,太棒了,我也使用了 bluetooth.close() 呵呵。问题在几秒钟内解决了! - Salvatorelab
看起来他们在4.2中更改了BluetoothSocket.close的实现。 - snak
这可能会对其他人有所帮助,但我的问题是我在不同的线程中调用了 Canvas.drawLine()(在完全不同的画布/位图上)。在极少数情况下,该方法(使用内部 C 代码进行绘制?)将在完全相同的时间访问并崩溃。 - IAmGroot
显示剩余2条评论

8

昨天我遇到了同样的错误。这种情况经常发生,但不一定总是如此。造成这个问题的原因迄今未被提及。

我认为自己可能有类似的问题,因为我也在处理线程,然而我删除了所有的线程操作,问题仍然存在。最终,在大量打印语句后,我成功地把问题追踪到一个类的实例身上。这个类有一个指针作为私有成员,但我忘记初始化这个指针。

后来,当这个类销毁时,它试图删除指针,但由于指针没有初始化为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帮助我追踪错误方面表现更好,因为它似乎更加挑剔。


为什么要踩?我不明白为什么确保指针初始化是一件坏事,特别是当它也导致了问题的错误。 - PolyMesh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接