Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does the compiler allocate memory without knowing the size at compile time?

I wrote a C program that accepts integer input from the user, that is used as the size of an integer array, and using that value it declares an array of given size, and I am confirming it by checking the size of the array.

Code:

#include <stdio.h> int main(int argc, char const *argv[]) {     int n;     scanf("%d",&n);     int k[n];     printf("%ld",sizeof(k));     return 0; } 

and surprisingly it is correct! The program is able to create the array of required size.
But all static memory allocation is done at compile time, and during compile time the value of n is not known, so how come the compiler is able to allocate memory of required size?

If we can allocate the required memory just like that then what is the use of dynamic allocation using malloc() and calloc()?

like image 259
Rahul Avatar asked Sep 24 '17 06:09

Rahul


People also ask

How does a compiler allocate memory?

When a variable is declared compiler automatically allocates memory for it. This is known as compile time memory allocation or static memory allocation. Memory can be allocated for data variables after the program begins execution. This mechanism is known as runtime memory allocation or dynamic memory allocation.

Is memory allocated at compile time in Java?

You may be confused with memory allocation sizes that can be determined at compile time versus memeory allocations that are unknown until runtime. The size of a reference is not known until the program runs. A 64-bit JVM can use either 32-bit or 64-bit references.

Does the compiler allocate memory for comments?

Or will the compiler always allocate exact or extra memory? All the compiler allocates in your example is memory for the global variable, which ends up in data/bss segment and not on the stack. The compiler/linker knows how much RAM it can use for data/bss and will hopefully tell you when you run out of that memory.


1 Answers

This is not a "static memory allocation". Your array k is a Variable Length Array (VLA), which means that memory for this array is allocated at run time. The size will be determined by the run-time value of n.

The language specification does not dictate any specific allocation mechanism, but in a typical implementation your k will usually end up being a simple int * pointer with the actual memory block being allocated on the stack at run time.

For a VLA sizeof operator is evaluated at run time as well, which is why you obtain the correct value from it in your experiment. Just use %zu (not %ld) to print values of type size_t.

The primary purpose of malloc (and other dynamic memory allocation functions) is to override the scope-based lifetime rules, which apply to local objects. I.e. memory allocated with malloc remains allocated "forever", or until you explicitly deallocate it with free. Memory allocated with malloc does not get automatically deallocated at the end of the block.

VLA, as in your example, does not provide this "scope-defeating" functionality. Your array k still obeys regular scope-based lifetime rules: its lifetime ends at the end of the block. For this reason, in general case, VLA cannot possibly replace malloc and other dynamic memory allocation functions.

But in specific cases when you don't need to "defeat scope" and just use malloc to allocate a run-time sized array, VLA might indeed be seen as a replacement for malloc. Just keep in mind, again, that VLAs are typically allocated on the stack and allocating large chunks of memory on the stack to this day remains a rather questionable programming practice.

like image 175
AnT Avatar answered Oct 04 '22 15:10

AnT