I was experimenting with realloc
, giving it larger and larger sizes and checking whether the same block was reused or not:
int main ( void )
{
char * newstr, * prevstr = NULL;
size_t newsize, prevsize = 0;
printf ("We play with realloc\n");
while (1) {
newsize = prevsize + 1 + prevsize/3; /* add 33% */
newstr = realloc(prevstr, newsize);
if (newstr == NULL) {
printf ("could not alloc newsize=%zu. Sorry\n", newsize);
break;
} else {
printf ("newsize=%zu successfully alloc'ed\n", newsize);
if (newstr == prevstr) {
printf ("newstr = prevstr:\tSame block reused\n");
} else {
printf ("newstr != prevstr:\tNew block alloc'ed\n");
}
prevstr = newstr; prevsize = newsize;
}
}
return (EXIT_SUCCESS);
}
As expected, one eventually reaches a point where the size is too large and realloc
cannot answer the request. According to the manual, realloc
should return NULL
and set errno = ENOMEM
when it does not succeed.
This is not what happens when I run the above code on my machine, a Mac with "Darwin Kernel Version 15.0.0". Instead of returning NULL, the code crashes and says
malloc: *** mach_vm_map(size=153288611651584) failed (error code=3)
*** error: can't allocate region
*** set a breakpoint in malloc_error_break to debug
could not alloc newsize=153288611651277. Sorry
Is this normal? Something I did not understand when reading the man page?
This is not crucial for my code at the moment but I can imagine situations where I'd like to test whether memory can be alloc'ed without risking a crash. Is there a standard way of testing whether alloc will work without risking such crash?
ADDED after mystery is solved (see answers below): there is no crash, just some system error message from malloc that gets in the way of the expected output. See below on how to avoid that.
Memory allocation failures can occur due to latencies that are associated with growing the size of a page file to support additional memory requirements in the system.
Usually on modern machines it will fail due to scarcity of virtual address space; if you have a 32 bit process that tries to allocate more than 2/3 GB of memory1, even if there would be physical RAM (or paging file) to satisfy the allocation, simply there won't be space in the virtual address space to map such newly ...
In the above example, if new fails to allocate memory, it will return a null pointer instead of the address of the allocated memory. Note that if you then attempt indirection through this pointer, undefined behavior will result (most likely, your program will crash).
As the comments have stated, there is no crash on allocation failure, only an error message.
If the message annoys you, you can turn it off by re-directing malloc
's log to /dev/null
, like this:
export MallocLogFile=/dev/null
Output before setting the environment variable looks like this:
newstr = prevstr: Same block reused
a.out(4275,0x7fff7146e000) malloc: *** mach_vm_map(size=153288611651584) failed (error code=3)
*** error: can't allocate region
*** set a breakpoint in malloc_error_break to debug
could not alloc newsize=153288611651277. Sorry
After setting the variable the output looks like this:
newstr = prevstr: Same block reused
could not alloc newsize=153288611651277. Sorry
Note: This is highly Mac-specific. See documentation for description of other environment variables that tweak the details of malloc
's operation.
Code did not crash as "could not alloc newsize=153288611651277. Sorry" output occurred - just an additional message was printed. @Blagovest Buyukliev
The additional message is likely sent out on stderr
rather than stdout
. @Eugene Sh.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With