What if malloc fails?

19,173

Solution 1

In general, a modern malloc() implementation will return NULL only as an absolute last resort, and trying again will definitely not help. The only thing that will help is freeing some memory and then trying again. If your application holds any expendable resources, this would be the time to free them, and then give it another shot.

In some environments, a useful practice is to allocate a small amount of memory as a rainy-day fund. If malloc() ever does return NULL, you can free that rainy-day fund, and then allocate whatever resources you need to be able to handle the error and exit gracefully. This was a common practice when programming with the old Macintosh Toolbox; if malloc() returned NULL, you could use that space to create a dialog to report the problem before exiting.

Solution 2

In a single-threaded program "trying again" without freeing any memory between tries make no practical sense. It will just loop forever.

In a multi-threaded program this might "work", if another thread running in parallel suddenly decides to free some of its own memory. The loop in such case would constitute a classic "busy waiting" loop. But even in this case such code has very little practical value for more reasons than one.

Solution 3

No, never. If malloc returns NULL, that indicates an error, and you should probably abort.

Solution 4

Without arguing why or when this would be useful, attempts to reallocate in a loop could work, at least on Windows with 64 bit code, and default pagefile settings. Moreover, this could buy surprisingly more additional virtual memory. Although, do not do this in an infinite loop, but instead use a finite number of retries. As a proof, try the following code that simulates leaking 1 Mb of memory. You have to run it in Release build, preferably not under debugger.

for (int i = 0; i < 10; i++)
{
  size_t allocated = 0;
  while (1)
  {
    void* p = malloc(1024 * 1024);
    if (!p)
      break;

    allocated += 1;
  }

  //This prints only after malloc had failed.
  std::cout << "Allocated: " << allocated << " Mb\n";
  //Sleep(1000);
}

On my machine with 8 Gb of RAM and system managed pagefile, I get the following output (built with VS2013 for x64 target, tested on Windows 7 Pro):

Allocated: 14075 Mb
Allocated: 16 Mb
Allocated: 2392 Mb
Allocated: 3 Mb
Allocated: 2791 Mb
Allocated: 16 Mb
Allocated: 3172 Mb
Allocated: 16 Mb
Allocated: 3651 Mb
Allocated: 15 Mb

I don't know exact reason of such behavior, but it seems allocations start failing once the pagefile resizing cannot keep up with requests. On my machine, pagefile grew from 8 gb to 20 Gb after this loop (drops back to 8 Gb after the program quits).

Solution 5

It is incredibly unlikely that this will do what you want; if you're out of memory, busy-looping until you get more is likely to be disappointing. You should just return the NULL to the calling program so that it can deal with resource exhaustion, either by releasing memory it no longer needs or by returning an error.

Share:
19,173

Related videos on Youtube

sam32
Author by

sam32

Updated on September 18, 2022

Comments

  • sam32
    sam32 over 1 year

    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?

  • R.. GitHub STOP HELPING ICE
    R.. GitHub STOP HELPING ICE over 11 years
    It could make sense even in a single-threaded program if the cause of the failure is exhaustion of total memory on the system and not just a per-process limit such as the size of virtual address space or a setrlimit limit.
  • 0kcats
    0kcats about 4 years
    A reference that may explain this: Memory allocation errors can be caused by slow page file growth. support.microsoft.com/en-us/help/4055223/…
  • 0kcats
    0kcats about 4 years
    A great answer to a related question: stackoverflow.com/a/14181163/2986286
  • chqrlie
    chqrlie over 3 years
    I'm afraid you are mistaken: s is a pointer to char, sizeof(s) is the size of a pointer, not the number of bytes required to store the string pointed to by s. strlen(s) + 1 is absolutely correct as char has a size of 1 byte by definition, casting to (char *) is optional but harmless if malloc() was properly declared by including <stdlib.h>.