【发布时间】:2011-06-24 12:42:23
【问题描述】:
我正在用 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 是我的自定义包装器,如果malloc 返回NULL,它只会调用exit,因此它不会耗尽内存。
如果我用-ltcmalloc 链接相同的代码,它可以正常工作,所以我强烈怀疑这是 OS X 10.5 的默认分配器中的某个错误。可能是我的程序在某处造成了一些内存损坏,而tcmalloc 并没有被它绊倒。我试图通过在不同的程序中执行相同的mallocs 和frees 序列来重现失败,但效果很好。
所以我的问题是:
以前有人见过这个错误吗?或者,或者,
如何调试这样的东西?例如,是否有 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)感兴趣,所以谢谢。
【问题讨论】:
-
“所以我强烈怀疑这是 OS X 10.5 的默认分配器中的某个错误”:不,不是。你在某处破坏记忆。你试过在 valgrind 下运行吗?
-
这几乎可以肯定是你的程序中的一个错误,它破坏了堆。
-
它可能是
malloc中的错误,但请记住:当开发人员说“我怀疑库中有错误”时,他们有 90% 的可能性重新错了。 (类似地,当库编写者说“我怀疑内核中存在错误”时,他们有 90% 的可能性是错误的;当内核工程师说“我怀疑硬件中存在错误”时,有 90% 的可能性他们也错了)。在这种情况下,您的代码看起来像是在使用 malloc 的内部数据结构之一;因为 tcmalloc 有不同的内部数据结构,使用它可以避免这个问题。 -
@stephen:对于像 malloc 这样基本的东西,我想说几率远高于 90%。让我想起了一个“程序员”,他在 strcat 中“发现”(并报告)了一个“错误”,不知道目的地需要空间来保存连接结果。
-
@xcramps:哦,我知道,我当时非常保守(实际数字更像是 99.99%)。还有@nominolo:我怀着极大的同情说这一切,因为有人 (a) 发表了这样的声明,并且 (b) 发现了库、内核和硬件中的合法错误。