On this site there is the following paragraph (emphasis mine):
- automatic storage duration. The storage is allocated when the block in which the ob
From the N1570 draft of the C11 specification §6.2.4/7
For such an object that does have a variable length array type, its lifetime extends from the declaration of the object until execution of the program leaves the scope of the declaration.
The specification then adds this helpful note:
Leaving the innermost block containing the declaration, or jumping to a point in that block or an embedded block prior to the declaration, leaves the scope of the declaration.
So the VLA is de-allocated when the execution goes outside the scope of the VLA, which includes the section in the same block before the declaration of the VLA.
Jumping to a point prior to the declaration can be done with a goto
statement. For example:
int n = 0;
while (n < 5)
{
top:
n++;
char array[n];
if (n < 2)
goto top;
}
In this code, the block is not exited when the goto
is executed. However, the value of n
changes, so a new array
needs to be allocated. That's the horribly convoluted situation that the specification is trying to support.
What is the difference between a declaration going out of scope and a block being exited? Can you provide an example?
The scope of a block-scope identifier starts at its declaration and extends to the end of the innermost enclosing block. This applies to identifiers of every kind, not just those of VLAs. It is possible for control to leave the scope of an identifier without exiting the innermost block containing it by transferring to a point preceding the identifier's declaration. The most obvious way to accomplish that would be via a goto
statement:
int f(int n) {
// i is allocated here, _before_ the beginning of its scope
label: // if control returns here via the goto below, vla is _de_allocated
// at this point
printf("n is %d", n);
int vla[n]; // vla is (re)allocated here, at the beginning of its scope
int i;
int sum;
for (i = 0; i < n; i++) {
vla[i] = rand();
sum += vla[i];
}
if (sum < SOME_THRESHOLD) goto label;
return sum; // vla and i are both deallocated when control exits the block
}
The difference in when a VLA is deallocated vs. when an ordinary automatic object is deallocated mirrors the difference between when the two types of objects are allocated. VLA's live only within the scope of their identifiers.