我正在用C语言编写程序。我有两台主要的开发机器,都是Mac。一个运行OS X 10.5,是32位机器,另一个运行OS X 10.6并且是64位。该程序在64位机器上编译和运行时工作正常。但是,当我在32位机器上编译完全相同的程序时,它会运行一段时间,然后在malloc
内的某处崩溃。这是回溯:
Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0xeeb40fe0
0x9036d598 in small_malloc_from_free_list ()
(gdb) bt
#0 0x9036d598 in small_malloc_from_free_list ()
#1 0x90365286 in szone_malloc ()
#2 0x903650b8 in malloc_zone_malloc ()
#3 0x9036504c in malloc ()
#4 0x0000b14c in xmalloc (s=2048) at Common.h:185
...
xmalloc
是我的自定义包装器,如果exit
返回malloc
,则只调用NULL
,因此内存不足。
如果我将相同的代码与-ltcmalloc
链接,它可以正常工作,所以我强烈怀疑它是OS X 10.5默认分配器中的某个错误。可能是我的程序在某处造成了一些内存损坏,并且tcmalloc
不知何故不会被它绊倒。我试图通过在不同的程序中执行相同的malloc
和free
s序列来重现失败,但这样做很好。
所以我的问题是:
之前有没有人见过这个bug?或者,或者
我该如何调试这样的东西?例如,是否有OS X的调试版malloc
?
$ otool -L ./interp
./interp:
/usr/lib/libgcc_s.1.dylib (compatibility version 1.0.0, current version 1.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 111.1.5)
更新:是的,由于从数组中读出结束而导致堆损坏,现在正在运行。我应该在发布问题之前运行valgrind
。然而,我对技术(除了valgrind)如何防止这种腐败感兴趣,所以,谢谢你。
答案 0 :(得分:4)
您是否在MacOS X上阅读了malloc()
的手册页?在某种程度上,它说:
提供了许多工具来帮助调试应用程序中的分配错误。这些 设施主要通过环境变量来控制。公认的环境变量 它们的含义记录在下面。
以下环境变量会更改与分配相关的函数的行为。
MallocLogFile <f>
创建/附加消息到给定的文件路径而不是写入 标准错误。
MallocGuardEdges
如果设置,请在每个大块之前和之后添加一个保护页面。
MallocDoNotProtectPrelude
如果设置,请不要在大块之前添加保护页面,即使是 已设置MallocGuardEdges环境变量。
MallocDoNotProtectPostlude
如果设置,请不要在大块后添加保护页面,即使是 已设置MallocGuardEdges环境变量。
MallocStackLogging
如果设置,则记录所有堆栈,以便可以使用泄漏等工具。
MallocStackLoggingNoCompact
如果设置,则以与。兼容的方式记录所有堆栈 malloc_history程序。
MallocStackLoggingDirectory
如果设置,则将堆栈日志记录到指定的目录而不是保存 它们到默认位置(/ tmp)。
MallocScribble
如果设置,请填充已分配0xaa字节的内存。这个 增加程序对新分配的内存的内容做出假设的可能性。如果设置,则填充内存 已被解除分配0x55字节。这增加了可能性 由于访问不再分配的内存,程序将失败。
MallocCheckHeapStart <s>
如果设置,则指定在开始之前要等待的分配数
<s>
定期堆检查MallocCheckHeapEach指定的每<n>
。如果 已设置MallocCheckHeapStart,但未指定MallocCheckHeapEach 默认检查重复是1000。
MallocCheckHeapEach <n>
如果设置,请在每个
<n>
操作的堆上运行一致性检查。 MallocCheckHeapEach仅在MallocCheckHeapStart也有意义时才有意义 集。
MallocCheckHeapSleep <t>
设置要休眠的秒数(等待调试器附加) 设置MallocCheckHeapStart并检测到堆损坏时。该 默认值为100秒。将此值设置为零意味着根本不睡觉。 将其设置为负数表示睡眠(对于正数 秒)只是第一次检测到堆损坏。
MallocCheckHeapAbort <b>
设置MallocCheckHeapStart并将其设置为非零值时 如果检测到堆损坏,则调用abort(3),而不是 任何睡觉。
MallocErrorAbort
如果设置,则在遇到错误时调用abort(3) malloc(3)或free(3),例如先前在指针上调用free(3) 释放。
MallocCorruptionAbort
与MallocErrorAbort类似,但在内存不足的情况下不会中止,因此只捕获那些会导致错误的错误更有用 记忆腐败。 MallocCorruptionAbort始终设置为64位进程。
尽管如此,我仍然首先使用valgrind
。
答案 1 :(得分:1)
有没有人在
之前看到过这个错误
是的,这是常见的编程错误,几乎可以肯定在您的代码中。见http://www.efnetcpp.org/wiki/Heap_Corruption
我该如何调试这样的东西?
请参阅上述链接的“工具”部分。