It is because the compiler must runtime-initialize the frame of the scope with VLAs. In other words, you tell it to jump to address :END
but you ask it to jump over the initialization code of the frame of that scope.
The code for initializing the space for the VLA is just before the expression that computes the length of the VLA. If you skip that code, which some goto can do, all the program will segfault.
Imagine something like:
if (cond) goto end;
...
char a[expr];
end:
a[i] = 20;
In this case the code will simply segfault, as you jump to the mutator of VLA a but a was not initialized. The code for initializing a VLA must be inserted in the place of the definition.
Now about alloca
. The compiler will do the same, but it is not able to detect a segfault.
So this will segfault, with no warning/error from the part of the compiler.
The logic is the same as for VLA.
int main(int argc, char *argv[])
{
goto end;
char *s = alloca(100);
end:
s[1] = 2;
return 0;
}
In ISO 9899 this is why they inserted the statement:
6.8.6.1 The goto statement -- Constraints
1 The identifier in a goto statement shall name a label located
somewhere in the enclosing function. A goto statement shall not jump
from outside the scope of an identifier having a variably modified
type to inside the scope of that identifier.
The compiler cannot detect during the static analysis the correct answer for this problem, as this is actually the halting problem
.