OS X 10.5 malloc中的错误?

时间:2011-02-09 23:57:04

标签: c crash malloc

我正在用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不知何故不会被它绊倒。我试图通过在不同的程序中执行相同的mallocfree s序列来重现失败,但这样做很好。

所以我的问题是:

  • 之前有没有人见过这个bug?或者,或者

  • 我该如何调试这样的东西?例如,是否有OS X的调试版malloc

BTW,这些是链接库:

$ 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)如何防止这种腐败感兴趣,所以,谢谢你。

2 个答案:

答案 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

  

我该如何调试这样的东西?

请参阅上述链接的“工具”部分。