Difference between array type and array allocated with malloc

Today I helped my friend with some C code, and I found strange behavior that I could not explain to him why this was happening. We had a TSV file with a list of integers, with int each line. The first line was the number of lines that had a list.

We also had a c file with a very simple "readfile". The first line was read in n, the number of lines, then there was initialization:

int list[n] 

and finally a for loop from n with fscanf.

For small n (up to ~ 100,000) everything was in order. However, we found that when n was large (10 ^ 6), segfault will occur.

Finally, we changed the initialization of the list to

 int *list = malloc(n*sizeof(int)) 

and all when good, even with very large n.

Can someone explain why this happened? what caused segfault with int list [n], which was stopped when we start using list = malloc (n * sizeof (int))?

+46
c arrays malloc variable-length-array
May 13 '12 at 9:52 pm
source share
9 answers

There are several different plays here.

The first is the difference between declaring an array as

 int array[n]; 

and

 int* array = malloc(n * sizeof(int)); 

In the first version, you declare an object with automatic storage time. This means that the array only works as long as the function that calls it exists. In the second version, you get memory with dynamic storage duration, which means that it will exist until it is explicitly freed using free .

The reason the second version works here is the implementation detail of how C is usually compiled. As a rule, C memory is divided into several areas, including the stack (for function calls and local variables) and the heap (for malloc ed objects). The stack is usually much smaller than the heap; this is usually something like 8 MB. As a result, if you try to allocate a huge array using

 int array[n]; 

You can then exceed the stack storage space by invoking segfault. On the other hand, a heap usually has a huge size (say, so much free space in the system), and therefore a malloc large object will not cause an error from memory.

In general, be careful with variable-length arrays in C. They can easily exceed the stack size. I prefer malloc if you don’t know that the size is small or you really need an array for a short period of time.

Hope this helps!

+104
May 13 '12 at 21:56
source share
 int list[n] 

Allocates space for n integers on the stack, which is usually quite small. Using memory on the stack is much faster than the alternative, but it is quite small and easily overflows the stack (i.e., it allocates too much memory) if you do things like allocating huge arrays or too much recursion. You do not need to manually release the allocated memory this way, this is done by the compiler when the array goes out of scope.

malloc , on the other hand, allocates space on the heap, which is usually very large compared to the stack. You will have to allocate a much larger amount of memory on the heap to release it, but it will be much slower to allocate memory on the heap than on the stack, and you must free it manually via free when you use it.

+8
May 13 '12 at 9:56 PM
source share

int list [n] stores the data on the stack, and malloc stores it on the heap.

The stack is limited, and there is not much space, and a lot more.

+2
May 13 '12 at 21:55
source share

int list[n] is a VLA that is allocated on the stack, not on the heap. You do not need to free it (it is automatically freed at the end of the function call), and it is allocated quickly, but the storage space is very limited, as you discovered. You must allocate large values ​​on the heap.

+1
May 13 '12 at 21:55
source share

This declaration allocates memory on the stack.

  int list[n] 

malloc allocates a bunch.

The stack size is usually smaller than the heap, so if you allocate too much memory on the stack, you get stackoverflow.

See also this answer for more information.

+1
May 13 '12 at 21:55
source share

Assuming you have a typical implementation in your implementation, most likely this:

 int list[n] 

a highlighted list on your stack, where as:

 int *list = malloc(n*sizeof(int)) 

allocated memory on your heap.

In the case of a stack, there is usually a limit to how large they can grow (if they can grow at all). In the case of the heap, there is still a limit, but it tends to be pretty much (and broadly) limited by your RAM + swap + address space, which is usually at least an order of magnitude larger, if not more.

+1
May 13 '12 at 21:56
source share

When you allocate using malloc , memory is allocated from the heap, not from the stack, which is much limited in size.

0
May 13 '12 at 21:55
source share

If you are using linux, you can set the ulimit -s value to a larger value, and this can also work for stack distribution. When you allocate memory on the stack, that memory remains until the end of your function execution. If you allocate memory on a heap (using malloc), you can free up memory at any time (even before the end of your function).

Typically, heaps should be used for large memory allocations.

0
May 14 '12 at 4:41
source share
  int array[n]; 

This is an example of a statically allocated array, and at compile time the size of the array will be known. And the array will be allocated on the stack.

  int *array(malloc(sizeof(int)*n); 

This is an example of a dynamically allocated array, and the size of the array will be known to the user at runtime. And the array will be allocated on the heap.

0
Jul 31 '16 at 14:22
source share



All Articles