Well, these are just a few wild stabs in the dark, based on the restrictions around VLA's, but anyway:
VLA's can't be:
- extern
- struct members
- static
- declared with unspecified bounds (save for function prototype)
All this points to VLA's being allocated on the stack, rather than the heap. So yes, VLA's probably are the last chunks of stack memory allocated whenever a new block is allocated (block as in block scope, these are loops, functions, branches or whatever).
That's also why VLA's increase the risk of Stack overflow, in some cases significantly (word of warning: don't even think about using VLA's in combination with recursive function calls, for example!).
This is also why out-of-bounds access is very likely to cause issues: once the block ends, anything pointing to what Was VLA memory, is pointing to invalid memory.
But on the plus side: this is also why these arrays are thread safe, though (owing to threads having their own stack), and why they're faster compared to heap memory.
The size of a VLA can't be:
- an
extern
value
- zero or negative
the extern restriction is pretty self evident, as is the non-zero, non-negative one... however: if the variable that specifies the size of a VLA is a signed int, for example, the compiler won't produce an error: the evaluation, and thus allocation, of a VLA is done during runtime, not compile-time. Hence The size of a VLA can't, and needn't be a given during compile-time.
As MichaelBurr rightly pointed out, VLA's are very similar to alloca
memory, with one, IMHO, crucial distinction: memory allocated by alloca
is valid from the point of allocation, and throughout the rest of the function. VLA's are block scoped, so the memory is freed once you exit the block in which a VLA is used:
void alloca_diff( void )
{
char *alloca_c, *vla_c;
for (int i=1;i<10;++i)
{
char *alloca_mem = alloca(i*sizeof(*alloca_mem));
alloca_c = alloca_mem;//valid
char vla_arr[i];
vla_c = vla_arr;//invalid
}//end of scope, VLA memory is freed
printf("alloca: %c\n", *alloca_c);//fine
printf("vla: %c\n\", *vla_c);//undefined behaviour... avoid!
}//end of function alloca memory is freed, irrespective of block scope
VLA works by placing the array in the stack
- https://mcmap.net/q/297416/-is-there-any-overhead-for-using-variable-length-arrays. That is also what I see when checking the assembly output generated by gcc when using a VLA, no call tomalloc
. But it might depend on the actual implementation. – Eeriemalloc
to imlement VLA because malloc can fail. Allocating a VLA is guaranteed to succeed if there is sufficient stack space available. malloc is never guaranteed to succeed. – Stallionmalloc
to implement VLA's :) – Reliancemalloc
are guaranteed to work indefinitely. In most common C implementations, usingmalloc
for variable-length arrays would support larger variable-length arrays than using the stack, because the space available for dynamic allocation is much larger than the default stack size. – Unclearmalloc
also succeeds if there is space available and fails if there is not. The C standard does not make actual guarantees about behavior in either case: A C implementation could fail to allocate a variable-length array (and terminate the program) even if there is theoretically more stack space available. A claim that variable-length arrays are more reliable is not sustainable in today’s environment where most C programs have gigabytes of memory available formalloc
but only a few megabytes for variable-length arrays. – Unclearmalloc
the standard clearly defines what happens on failure. In a way this is more "reliable" but you have no guarantee that malloc will work, regardless of how many gigabytes you think you have. – Stallion