What if malloc fails?

Viewed 20583

If a malloc allocation fails, should we try it again?

In something like this:

char* mystrdup(const char *s)  
{
    char *ab = NULL;

    while(ab == NULL) {
        ab=(char*)malloc(strlen(s)+1);  
    }

    strcpy(ab, s);
    return ab;
}

Is the while loop valid for checking the memory allocation?

10 Answers

Its depends on what is your sofware for and what part of your code is affected.

First to know, malloc() can fail when no pages available, if your application reached it's limit then will not work any loop, but if your system ran out of memory it worth a try, but you must avoid any infinte loops. Surprise! Perfectly normal if the operating system temporarily response that could not allocate more RAM, you can handle at your way.

This is a very good question anyway

Similar problem is not capturing SIGNALS and when a multi-threaded or async TCP server got an aborted client connection the software terminated by SIGPIPE. This is normal, but leads to end your program however its should not. To prevent this, you have to hook for signals.

In realworld examples (my own).

When malloc fails and only affect partially of my code

I used to malloc() or new[] when new connection sending data, Im storing received data into buffers, if malloc or realloc fails, the function return as false and free the buffer, the connection dropped with error (lingerie) so in this case the software continue to run but one connection dropped. I think this is a right way here.

When malloc must cause software abort

I used to malloc() to make space for critical data, like arrays, structures that defines the core, this is usually run at the begining of the software as init section, if there is malloc() fail the software must abort and exit with error code, because all operation depending on the tables that must filled with data. (Built-In-Filesystem)

When malloc able to retry

I had my datalogger software which is some industry-leading type (High-Availability), if malloc() fails I trigger a mutex_lock() which cause software freeze in backend side and trying to retry the malloc procedure for X seconds. If malloc() continues to fail the software starting to call destructors on all threads and performs a complete shutdown except that thread which is tried to malloc() unsuccessful at this point there are two option, malloc() succeed and finish the stack call and exit the last thread or doing a rollback and exit the last thread.

Whenever is happening the software does not quit as well, try to start from begining and so on..

Maybe worth to mention ..

I had exactly the same dilemma years ago, something caused a memory leak in my software and ate all of my RAM but to save the current state I had to write it out which done after many malloc(), the solution was when this happened I closed all threads and calls destructors and saved the data, however the interesting thing was when I closed all connections and free'd up socket, ssl_ctx, ... memory consumption dropped to 128KB, after days of happy debugging I figured it out that SSL_CTX has internal storage and cache. So now when no connection online I free up SSL_CTX and works like a charm.

SUMM

So as you can see this is an art, you do what you want with malloc() and anything its just up to you, there is no book and no standard what you should do if malloc() fails. If someone tells you what you should do its just his opinion nothing more.

my preferred way to avoid infinte loops

PSEUDO CODE:

var ts = TIME()
var max_seconds = 5
var success = true

WHILE (MALLOC() == FAIL) DO
   IF TS + max_seconds < TIME() THEN
      success = false
      BREAK
   END
   SLEEP(100ms)
END


In my experience (UNIX) it is MOST important to handle malloc failures robustly immediately following a network administrators boast that the "new server you wanted is already out there and ready to go". To which a typical reply is something like: "Wow, that was fast, thanks". Its at THIS point that malloc will return a NULL.

Best thing to do is throw a std::bad_alloc exception with a static error message which gets caught & displayed in main(). Hopefully your destructors do enough cleanup freeing memory that the error processing in main does not fail.

If you use a reasonable OS and programming style, an OOM condition is recoverable.

You are not properly allocating memory malloc function require argument as number of bytes it needs to allocated but you are passing the length of the string so the malloc will reserve memory as per length not per the byte used by your string . You should use sizeof() instead and if still it fails then malloc returns null which represent that there is not enough memory available in the stack to satisfy your requirement. To run your code properly try this:-

char* mystrdup(const char *s)
{ char *ab = NULL;

while(ab == NULL) {
    ab=(char*)malloc(sizeof(s));  
}

strcpy(ab, s);
return ab;

}

Related