What if malloc fails?
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.
Related videos on Youtube
sam32
Updated on September 18, 2022Comments
-
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 over 11 yearsIt 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 about 4 yearsA reference that may explain this: Memory allocation errors can be caused by slow page file growth. support.microsoft.com/en-us/help/4055223/…
-
0kcats about 4 yearsA great answer to a related question: stackoverflow.com/a/14181163/2986286
-
chqrlie over 3 yearsI'm afraid you are mistaken:
s
is a pointer tochar
,sizeof(s)
is the size of a pointer, not the number of bytes required to store the string pointed to bys
.strlen(s) + 1
is absolutely correct aschar
has a size of 1 byte by definition, casting to(char *)
is optional but harmless ifmalloc()
was properly declared by including<stdlib.h>
.