OS X 10.5 malloc 中的错误?

发布于 2024-10-16 20:29:50 字数 1413 浏览 0 评论 0原文

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

所以我的问题是:

  • 以前有人见过这个错误吗?或者,

  • 我如何调试这样的东西?例如,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 之外)很感兴趣,所以谢谢你。

I'm writing a program in C. I have two main development machines, both Macs. One is running OS X 10.5 and is a 32bit machine, the other is running OS X 10.6 and is 64 bits. The program works fine when compiled and run on the 64bit machine. However, when I compile the exact same program on the 32bit machine it runs for a while and then crashes somewhere inside malloc. Here's the backtrace:

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 is my custom wrapper which just calls exit if malloc returns NULL, so it's not running out of memory.

If I link the same code with -ltcmalloc it works fine, so I strongly suspect that it's a bug somewhere inside OS X 10.5's default allocator. It may be that my program is causing some memory corruption somewhere and that tcmalloc somehow doesn't get tripped up by it. I tried to reproduce the failure by doing the same sequence of mallocs and frees in a different program but that worked fine.

So my questions are:

  • Has anyone seen this bug before? Or, alternatively

  • How can I debug something like this? E.g., is there a debug version of OS X's malloc?

BTW, these are the linked libraries:

$ 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)

Update: Yeah, it's heap corruption due to writing past the end off an array, it's working now. I should have run valgrind before posting the question. I was nevertheless interested in techniques (other than valgrind) how to protect from such kind of corruption, so thanks for that.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

橘虞初梦 2024-10-23 20:29:50

您读过 MacOS X 上 malloc() 的手册页吗?它的部分内容是:

调试分配错误

提供了许多工具来帮助调试应用程序中的分配错误。这些
设施主要通过环境变量进行控制。识别的环境变量
它们的含义记录如下。

环境

以下环境变量会更改与分配相关的函数的行为。

  • MallocLogFile

    创建/追加消息到给定的文件路径而不是写入
    标准错误。

  • MallocGuardEdges

    如果设置,则在每个大块之前和之后添加一个防护页。

  • MallocDoNotProtectPrelude

    如果设置,请勿在大块之前添加保护页,即使
    MallocGuardEdges 环境变量已设置。

  • MallocDoNotProtectPostlude

    如果设置,请勿在大块之后添加保护页,即使
    MallocGuardEdges 环境变量已设置。

  • MallocStackLogging

    如果设置,则记录所有堆栈,以便可以使用泄漏等工具。

  • MallocStackLoggingNoCompact

    如果设置,则以与
    malloc_history 程序。

  • MallocStackLoggingDirectory

    如果设置,则将堆栈日志记录到指定目录而不是保存
    将它们复制到默认位置 (/tmp)。

  • MallocScribble

    如果设置,则用 0xaa 字节填充已分配的内存。这
    增加了程序对新分配的内存的内容进行假设失败的可能性。另外,如果设置,则填充内存
    已被释放 0x55 字节。这增加了可能性
    程序将由于访问不再分配的内存而失败。

  • MallocCheckHeapStart

    如果设置,则指定开始之前要等待的分配数量
    定期堆检查 MallocCheckHeapEach 指定的每个 。如果
    设置了 MallocCheckHeapStart 但未指定 MallocCheckHeapEach,则
    默认检查重复次数为 1000。

  • MallocCheckHeapEach

    如果设置,则每次 操作都会对堆运行一致性检查。
    仅当 MallocCheckHeapStart 也为时 MallocCheckHeapEach 才有意义
    设置。

  • MallocCheckHeapSleep

    设置休眠秒数(等待调试器连接)
    当设置 MallocCheckHeapStart 并检测到堆损坏时。这
    默认值为 100 秒。将其设置为零意味着根本不睡觉。
    将其设置为负数意味着睡眠(对于正数
    秒)仅在第一次检测到堆损坏时。

  • MallocCheckHeapAbort

    当设置 MallocCheckHeapStart 并且将其设置为非零值时,
    如果检测到堆损坏,则导致调用 abort(3),而不是
    任何睡眠。

  • MallocErrorAbort

    如果设置,则在遇到错误时会调用 abort(3)
    malloc(3) 或 free(3) ,例如之前在指针上调用 free(3)
    获释。

  • MallocCorruptionAbort

    与 MallocErrorAbort 类似,但不会在内存不足的情况下中止,这使得仅捕获那些会导致错误的错误更加有用
    内存损坏。 MallocCorruptionAbort 始终在 64 位进程上设置。



也就是说,我仍然会首先使用 valgrind。

Have you read the manual page for malloc() on MacOS X? In part, it says:

DEBUGGING ALLOCATION ERRORS

A number of facilities are provided to aid in debugging allocation errors in applications. These
facilities are primarily controlled via environment variables. The recognized environment variables
and their meanings are documented below.

ENVIRONMENT

The following environment variables change the behavior of the allocation-related functions.

  • MallocLogFile <f>

    Create/append messages to the given file path instead of writing to
    the standard error.

  • MallocGuardEdges

    If set, add a guard page before and after each large block.

  • MallocDoNotProtectPrelude

    If set, do not add a guard page before large blocks, even if the
    MallocGuardEdges environment variable is set.

  • MallocDoNotProtectPostlude

    If set, do not add a guard page after large blocks, even if the
    MallocGuardEdges environment variable is set.

  • MallocStackLogging

    If set, record all stacks, so that tools like leaks can be used.

  • MallocStackLoggingNoCompact

    If set, record all stacks in a manner that is compatible with the
    malloc_history program.

  • MallocStackLoggingDirectory

    If set, records stack logs to the directory specified instead of saving
    them to the default location (/tmp).

  • MallocScribble

    If set, fill memory that has been allocated with 0xaa bytes. This
    increases the likelihood that a program making assumptions about the contents of freshly allocated memory will fail. Also if set, fill memory
    that has been deallocated with 0x55 bytes. This increases the likelihood
    that a program will fail due to accessing memory that is no longer allocated.

  • MallocCheckHeapStart <s>

    If set, specifies the number of allocations <s> to wait before begining
    periodic heap checks every <n> as specified by MallocCheckHeapEach. If
    MallocCheckHeapStart is set but MallocCheckHeapEach is not specified, the
    default check repetition is 1000.

  • MallocCheckHeapEach <n>

    If set, run a consistency check on the heap every <n> operations.
    MallocCheckHeapEach is only meaningful if MallocCheckHeapStart is also
    set.

  • MallocCheckHeapSleep <t>

    Sets the number of seconds to sleep (waiting for a debugger to attach)
    when MallocCheckHeapStart is set and a heap corruption is detected. The
    default is 100 seconds. Setting this to zero means not to sleep at all.
    Setting this to a negative number means to sleep (for the positive number
    of seconds) only the very first time a heap corruption is detected.

  • MallocCheckHeapAbort <b>

    When MallocCheckHeapStart is set and this is set to a non-zero value,
    causes abort(3) to be called if a heap corruption is detected, instead of
    any sleeping.

  • MallocErrorAbort

    If set, causes abort(3) to be called if an error was encountered in
    malloc(3) or free(3) , such as a calling free(3) on a pointer previously
    freed.

  • MallocCorruptionAbort

    Similar to MallocErrorAbort but will not abort in out of memory conditions, making it more useful to catch only those errors which will cause
    memory corruption. MallocCorruptionAbort is always set on 64-bit processes.


That said, I'd still use valgrind first.

二手情话 2024-10-23 20:29:50

有人以前见过这个错误吗

吗?是的,这是常见的编程错误,几乎肯定存在于您的代码中。请参阅http://www.efnetcpp.org/wiki/Heap_Corruption

如何调试这样的东西?

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

Has anyone seen this bug before

Yes, this is common programming bug and is almost certainly in your code. See http://www.efnetcpp.org/wiki/Heap_Corruption

How can I debug something like this?

See the Tools section of the above link.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文