Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the difference between variable length array and dynamic memory allocation?

Tags:

c

int a[n];

vs

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

Could anyone explain pro and cons of both method respectively? (efficiency, security etc)

like image 533
realzhujunhao Avatar asked Feb 20 '26 13:02

realzhujunhao


2 Answers

The main difference is the VLA declaration introduces a new Variably Modified (VM) type and that the object has automatic storage, the malloc() variant has dynamic storage.

The code:

int a[n];

is seen by compiler as:

int T_elems = n;
typedef int T[T_elems];
T a;

As result array a has automatic storage and it is allocated on stack on modern systems. Automatic means that the object's memory is released when leaving the scope were the objects was introduced.

int *b;
{
   int a[n];
   // `a` is valid
   b = a;
}
// resources pointed by `b` are released

On the other hand the second snippet:

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

Creates a pointer to int and assign an dynamically allocated object to it. The objects resources are valid even though scope of a has ended. The memory is valid until release with free().

int *b;
{
   int * a = malloc(n * sizeof(int));
   b = a;
}
// resources pointed by `b` are valid!
free(b);
// memory is no longer valid

There is a common misconception that VLA are always allocated on stack. VLAs can be allocated on heap via pointer to arrays:

int (*a)[n] = malloc(sizeof(int[n]));

Summary:

  1. VLAs (and VM types)

Pros:

  • simple allotaction of automatic VLAs
  • "always" succeeds (behavior on failure in undefined by C standard)
  • allocation is very fast (slightly slower than fixed arrays)
  • no risk of leaks for automatic VLAs
  • can have dynamic storage (via pointers to VLA)
  • very convenient for multidimensional arrays
  • carry its size thus sizeof a returns n * sizeof int

Cons:

  • automatic VLAs can easily overflow stack
  • VM types cannot be defined at file scope (cannot be returned)
  • VM types cannot be used as struct members
  • become optional feature since C11
  • operand of sizeof of VLA type is evaluated
  • automatic VLAs cannot be resized
  1. Dynamic 1D array.

Pros:

  • supported by all C standards
  • can be any size, no stack limit
  • indicates if allocation is successful, however on modern OS malloc() reserved address space. OS give little guarantee that the memory is reserrved
  • can be resized with realloc()

Cons:

  • more verbose syntax
  • must check if successful
  • allocations are slower than any stack-based allocations
  • memory must be released with free() to avoid leaks
  • do not carry size, one must keep size of array

The same data organized as a table:

Automatic VLA malloc
Syntax Simple More verbose
Behavior on error Stack overflow NULL
Error handling Impossible: behavior on failure is undefined Must check malloc's return value
Maximal size Stack size Heap size (larger than stack)
Speed Very fast (slightly slower than fixed arrays) Slower than any stack-based allocation
Deallocation Automatic; no risk of leaks Memory must be released with free() to avoid leaks
Array size support Yes, by sizeof No, programmer must store explicitly
Can return it? No Yes
Can put in struct? No Yes
Portability C99, Became optional feature since C11 Supported by all C standards
Supports resizing? No Yes, by realloc
Multi-dimensional Simple syntax Possibly confusing syntax
like image 106
tstanisl Avatar answered Feb 22 '26 13:02

tstanisl


VLAs behave (mostly) like any other auto variable - storage for them will automatically be released when you exit their enclosing scope. Dynamic memory will not be released until you explicitly free it.

VLAs are great when you need some temporary working storage that doesn’t need to be too big or hang around beyond the lifetime of its enclosing function. Like fixed-length local arrays, they cannot be arbitrarily large. Despite the name, variable-length arrays cannot be resized once they are defined - the "variable" in variable-length simply means that their size can be different each time it is instantiated.

You’d use dynamic memory when you don’t know until runtime how much memory you need and the allocated object has to live outside the lifetime of any specific function, or needs to be very large, or needs to be resizable (using realloc).

like image 40
John Bode Avatar answered Feb 22 '26 14:02

John Bode



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!