无法调试 I/DEBUG(187): 信号11(SIGSEGV),代码1(SEGV_MAPERR),故障地址00000004。

3
我正在开发一款Android应用程序,需要大量的内存分配(许多图像缓冲区)。我正在使用Android NDK进行开发。但是我遇到了奇怪的崩溃。我希望这不是重复的帖子(在查看以前的帖子后)。
应用程序崩溃,出现以下错误:I/DEBUG(187): signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 00000004
以下是解决此问题时需要考虑的几个方面:
1. 我之前遇到过分段错误,并且已经解决了它。
2. 我非常确定我正在正确地分配和释放内存,因为我在Windows上使用相同的设置,确认没有内存泄漏,并且我没有访问任何未分配的位置(无解引用,无错误指针)。在Windows上测试期间没有发现任何内存损坏。
3. 我也确信JNI调用的分配和释放在代码中的适当位置。内存仅在使用完成后清除。
4. 回溯显示每次崩溃发生时都有不同的API调用,其中发生错误。我已经记录下日志并且没有发现空指针,它们都符合预期。
5. 此崩溃非常随机。偶尔会发生,在应用程序内长时间运行时或在应用程序内执行许多操作时可能会发生。但大部分时间它都可以正常工作。
请问有人能够建议我的代码中内存是如何受损的,可能是什么原因导致了这种情况?
3个回答

6

请查找您在结构体或数组中可能访问字段的位置。我这么说的原因是因为故障地址为00000004,即在NULL地址后4个字节。检查每个字段的访问,特别是在执行大量代码的代码中。

此外,请检查malloc/new返回的NULL值,您的设备可能已经没有可用内存。

由于您说这个问题发生在执行大量操作或应用程序长时间运行时,请检查内存泄漏。您的应用程序可能会消耗所有设备内存。如果您有自定义的分配器/释放器,则可以使用全局计数器,每次分配增加,每次释放减少。如果计数器过高,则存在内存泄漏。


2

当堆栈被破坏时,崩溃的位置通常是随机的,因此您应该仔细查看本地变量。例如,使用M覆盖长度为N的数组等。


你好,感谢回复。我的本地代码有一个全局结构,其中包含指向不同缓冲区的指针。我有两个API,一个用于分配,一个用于释放。我一直在我的代码中使用这些API。例如,当我按下UI中的“完成”按钮时,我会释放资源。您是否发现任何可疑之处? - Nrupatunga
如果您分配的内存已经损坏,通常会在使用该内存的位置崩溃。如果您有全局分配和释放函数,可以尝试类似于MS编译器的方法。分配比请求稍多一点的内存,并在开头和结尾放置一些标记字节。当释放内存时,使用已知模式覆盖内存。这可能有助于检查是否仍在使用该内存。对于堆栈损坏,您只能尝试通过放置日志文件并找到重复触发崩溃的情况来确定问题所在。 - Devolus

1

故障地址00000004 => 表示堆栈已损坏(非常接近0地址)。

以下是一个示例,说明您如何通过意外取消引用字符串来轻松复制此错误:

int a = foo();
LOGE("Foo() is %d", a ? "ok" : "not ok"); 

应该是"%s"而不是"%d"

希望能对某些人有所帮助。


为什么您决定这是堆栈损坏?更有可能的是,它是通过空指针访问类实例的类数据成员。 - Megamozg

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