views:

191

answers:

4

I am allocating memory in a C program using malloc. It's possible for my program to allocate more memory than the system has room for, at which point the program crashes. For my purposes it would be better if malloc would just return NULL (like it's apparently supposed to), so I can catch the error. Instead what it does is it throws an error saying "No memory available to program now: unsafe to call malloc." And crashes the program.

How can I fix this?

Edit: I know that the program is crashing by itself and not because I'm trying to reference a null pointer. The program never directly calls malloc, but instead calls a function I wrote that calls malloc and then checks to see if it returns NULL. It's never saying that malloc returned NULL.

Edit 2: If it's helpful, here is the complete error output:

Program received signal: “EXC_BAD_ACCESS”.
sharedlibrary apply-load-rules all
warning: Unable to restore previously selected frame.
Data Formatters temporarily unavailable, will re-try after a 'continue'. (The program being debugged was signaled while in a function called from GDB.
GDB remains in the frame where the signal was received.
To change this behavior use "set unwindonsignal on"
Evaluation of the expression containing the function (dlopen) will be abandoned.)
No memory available to program now: unsafe to call malloc

+1  A: 

It checks to see if Malloc returns NULL? You may have a problem with the equality test. Try something like 'if (malloc(...)) then ...; else ...;' rather than a specific check.

If that fails to help then run just the preprocessor and work out what NULL is being 'edited' to be.

geoff marshall
"if (malloc(...)) then ...; else ..." has the same problem. NULL is edited to (void *)0, which is what you'd expect, isn't it?
Michael Dickens
Yes it is, but there could have been a mistaken redeclaration of NULL that made it something else. We know from the standard that non-NULL pointers are "true", so this was a reasonable dead chicken to wave over the problem...
RBerteig
+1  A: 

According to this apple page, the program will abort based on a malloc error if the MallocErrorAbort environment variable is turned on in xcode. To turn off this variable, right-click on the executable in the Tree view, select "Get Info," and go to the "Arguments" tab.

Spencer Nelson
It originally wasn't there, so I put it in and set it to 0. The problem was not fixed. The problem persists when I compile the program from the command line instead of from Xcode. Also, thanks for the link.
Michael Dickens
Then I set MallocErrorAbort to YES and the compiler gave me a message indicating that it was on. The program crashed in the same way.
Michael Dickens
+1  A: 

Strange ... the following works for me if I compile it from the command line. The runtime supplied malloc does have a lot of options as Spencer mentioned. If you are using XCode, I would look for an option that controls this.

#include <limits.h>
#include <stdio.h>
#include <stdlib.h>


int
main()
{
    signed long long alloc_sz = (1 * 1024 * 1024 * 1024);
    while (alloc_sz > 0ull) {
        char *ptr = malloc(alloc_sz);
        if (ptr == NULL) {
            fprintf(stderr, "failed to allocate %llu bytes\n",
                    (unsigned long long)alloc_sz);
            break;
        } else {
            free(ptr);
            fprintf(stderr, "allocated %llu bytes\n",
                    (unsigned long long)alloc_sz);
        }
        alloc_sz *= 2ull;
    }
    return 0;
}

BTW: is this in a debug or release build? It may be that XCode is trying to help you out somehow.

D.Shawley
I ran that code, and it gave some output and then `malloc` returned NULL. Now we know that something else is causing the problem. BTW: Debug build.
Michael Dickens
+2  A: 

Once you scribble on the heap via buffer overruns, wild pointers or other bugs, malloc's behavior becomes undefined and it could return anything.

Malloc is simply a user-space library; there isn't any magic contained within it. If I scribble all over your application's linked list of customer names, you'll get weird behavior when you later access that list. Malloc behaves in the same way, but since the use of malloc is distributed through the code, cause and effect have global reach.

All of the answers are dancing around the fact that pointer errors are the single most prevalent source of defects in C code. You are lucky you are getting a SIGBUS which is the evidence of defect that may be widely separated from where and when the fault occurs. Use valgrind to help you find where the real defect is.

msw
+1 for valgrind. If `malloc()` is doing impossible things, then it seems likely that you have inadvertently damaged some of the heap.
RBerteig
Thanks. I will install Valgrind. You make me think that probably what's happening is I'm putting too much stuff into an array and it's going off the end.
Michael Dickens
Oops, it looks like Valgrind isn't supported on OS 10.6. Short of installing a different operating system, do you know of any similar programs that work on 10.6?
Michael Dickens
Alas, the last time I touched a Mac, OS 8 was the new shiny. You might want to start a new "How to catch C pointer errors on MacOS X.6?" question as questions get stale around here pretty quickly.
msw