2

I'm running into a segfault when allocating a dynamic array of large size.

As a specific example, the below code causes a segfault.

int max = 1399469912;
int *arr = (int*) malloc((max+1) * sizeof(int));
arr[0] = 1;

However, if I replace max with something smaller like 5, then I get no segfault.

Why does this happen? Or, is there another solution to achieve the same effect? I need a dynamically allocated array of significant size.

Thanks

  • 4
    First of all, [should you really cast the result of `malloc`](http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc)? Secondly, what if the [`malloc`](http://en.cppreference.com/w/c/memory/malloc) call fails and return a null pointer? You need to *check* for that. – Some programmer dude Jun 08 '17 at 14:21
  • 3
    A is for Ambition. A is also for Allocation. Trying to allocate 5.6 gigabytes is a rather *Ambitious Allocation.* – Mike Nakis Jun 08 '17 at 14:23
  • 2
    If the arithmetic is done using 64-bit numbers, you're asking for about 5 GiB of memory. Does you system allow you to allocate that much? You must check the return value from `malloc()` before using it. That isn't always enough (Linux and OOM — Out of Memory — Killer), but it is necessary. – Jonathan Leffler Jun 08 '17 at 14:25
  • I have a hunch the OP is trying to do this on a 32 bit OS. – Paul R Jun 08 '17 at 14:26

3 Answers3

6

Reed documentation of malloc (or malloc(3) from Linux man page)

It can fail, and then returns NULL; and your code should handle that case:

int *arr = malloc((max+1) * sizeof(int));
if (!arr) { perror("malloc arr"); exit(EXIT_FAILURE); };

You could handle the failure in some other ways, but errno is giving the reason. In practice, recovering a malloc or calloc failure is quite tricky. In most cases, exiting abruptly like above is the simplest thing to do. In some cases (think of a server program which should run continuously) you can do otherwise (but that is difficult).

Read also about memory overcommitment (a whole system configurable thing or feature, that I personally dislike and disable, because it might make malloc apparently succeed when memory resources are exhausted; on Linux read about Out-of-memory killer)

See also this (a silly implementation of malloc)

BTW, you need to be sure that (max+1) * sizeof(int) is not overflowing, and you'll better define size_t max = 1399469912; (not int).

Notice that you are requesting (on systems having sizeof(int)==4 like my Linux/x86-64 desktop) more than five gigabytes. This is a significant amount of virtual address space.

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
3

You have to check whether malloc return a valid pointer or fails to allocate the memory. In that case, it returns a null. pointer.

int max = 1399469912;
int *arr = (int*) malloc((max+1) * sizeof(int));
if( arr == NULL )
{
     /* Malloc failed, deal with it */
}else{
 //fine here
 arr[0] = 1;
}

Quoting the man page

If successful, calloc(), malloc(), realloc(), reallocf(), and valloc() functions return a pointer to allocated memory. If there is an error, they return a NULL pointer and set errno to ENOMEM.

Davide Spataro
  • 7,319
  • 1
  • 24
  • 36
2

malloc() returns NULL if it wasn't able to allocate the requested memory. You should check the value returned by malloc() against NULL.

JFMR
  • 23,265
  • 4
  • 52
  • 76