开发者

Bug in OS X 10.5 malloc?

开发者 https://www.devze.com 2023-02-10 03:15 出处:网络
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 c

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开发者_JAVA技巧.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.


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.


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.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号