无效的堆地址和致命信号 11
Posted
技术标签:
【中文标题】无效的堆地址和致命信号 11【英文标题】:Invalid heap address and fatal signal 11 【发布时间】:2012-05-26 14:34:42 【问题描述】:我的应用程序经常崩溃,我的日志会显示:
@@@ ABORTING: INVALID HEAP ADDRESS IN dlfree
Fatal signal 11 (SIGSEGV) at 0xdeadbaad (code=1)
有时code=2
,但总是Fatal signal 11
和invalid heap address
。
我已经尝试研究这意味着什么以及如何解决它。 This thread has been the most helpful;但是,我仍然没有解决方案。
当我运行几个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
的其他线程,但在我的情况下它们并没有提供太多帮助。
【问题讨论】:
您的应用程序中是否有任何 JNI? 我的应用程序中确实有 JNI 并且收到此错误。任何建议,@JulieinAustin @WhitneyImura This question 讨论了当 JNI 导致此错误时该怎么做。 【参考方案1】:我昨天也遇到了同样的错误。它总是发生,但并不总是始终如一。到目前为止,我还没有提到是什么原因造成的。
我想我可能有类似的问题,因为我也在处理线程,但是我删除了所有线程,问题仍然存在。最后,在一堆打印语句之后,我能够将其追踪到我实例化的一个类,该类有一个指针作为私有成员,但我忘了初始化指针。
后来,当该类被破坏时,它试图删除指针,但是由于指针没有初始化为 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 在帮助我追踪错误方面取得了胜利,因为它似乎更加挑剔。
【讨论】:
为什么投反对票?我不明白为什么确保指针被初始化是一件坏事,尤其是当它也会导致相关错误时。【参考方案2】:我刚刚遇到了同样的问题,并且它处于可重现的状态。这是我得到的错误:
08-04 17:37:05.491: A/libc(4233): @@@ ABORTING: dlfree 中的堆地址无效 08-04 17:37:05.491: A/libc(4233): 0xdeadbaad (code=1) 处的致命信号 11 (SIGSEGV)
归结为同时从两个不同的线程进行函数调用。
更具体地说,这个函数是 BluetoothSocket 的 close() 方法。
我检查了源代码 at this website ,调用没有同步(不确定这是否改变了,因为它来自 android 2.1)。
无论如何,您是否有类似的场景,即从多个线程进行函数调用?从您显示的源代码中无法确定。
你也试过不使用 THREAD_POOL_EXECUTOR 吗?根据the android dev guide:
首次引入时,AsyncTask 是在单个后台线程上串行执行的。从 DONUT 开始,这被更改为允许多个任务并行运行的线程池。从 HONEYCOMB 开始,任务在单线程上执行,以避免并行执行导致的常见应用程序错误。
【讨论】:
您是如何发现导致您出现问题的方法是 BluetoothSocket 的 close() 方法? 我检查了代码,发现我几乎同时从两个不同的线程调用 close() 方法。 这个答案是绝对正确的。我有相同的错误代码(@@@ ABORTING: LIBC: ARGUMENT IS INVALID HEAP ADDRESS IN dlfree addr)。在我的特殊情况下,我有两个不同的线程调用 PathMeasure.getPosTan 方法。在我更改了代码以确保一次只能由一个线程调用后,错误就消失了。 哇,真的,我也在用bluetooth.close()
呵呵。问题在几秒钟内解决!
看来他们在4.2中更改了BluetoothSocket.close
的实现。以上是关于无效的堆地址和致命信号 11的主要内容,如果未能解决你的问题,请参考以下文章
致命信号11(SIGSEGV),代码1,tid 31051中的故障地址0x9
如何在tid xxxxx(Thread-X)中解决Android致命信号11(SIGSEGV),代码1,故障地址0x0?
MobileAds.initialize(this) 崩溃 致命信号 11 (SIGSEGV),代码 1 (SEGV_MAPERR)
A/libc:致命信号 11 (SIGSEGV),代码 1 (SEGV_MAPERR),tid 8890 (RenderThread) 中的故障地址 0x20,pid 8833