Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Memory allocation fails. But why does it crash? Or does it?

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.

like image 452
phs Avatar asked Nov 05 '15 15:11

phs


People also ask

What causes memory allocation failure?

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.

Why does memory allocation fail even when you have enough space?

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 ...

What happens if memory allocation fails?

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).


2 Answers

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.

like image 117
Sergey Kalinichenko Avatar answered Oct 17 '22 22:10

Sergey Kalinichenko


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.

like image 24
2 revs Avatar answered Oct 17 '22 23:10

2 revs