问题
After the second closing brace, b
is accessible only through indirection through a
.
int main() {
int *a;
{
int b = 42;
a = &b;
}
printf("%d", *a); // UB?
return 0;
}
Since b
is not anymore in scope, is this UB? I know it's UB to dereference a pointer to a non-static local variable from a function that has already returned, but in this case everything is within the same function.
This is UB in C++, but I'm not sure about C.
回答1:
Yes, it's undefined behaviour to access any variable that has reached it's end of life. Scope and storage duration are subtly different here. Scope is more "when is the variable identifier visible?" and storage duration is "when does the variable itself exist?".
You can have things in scope and enduring such as:
int main (void) {
int spoon = 42;
// spoon is both in scope and enduring here
return 0;
}
Or out of scope but enduring:
int main (void) {
int *pSpoon;
{
static int spoon = 42;
pSpoon = &spoon;
}
// spoon is out of scope but enduring here (use *pSpoon to get to it)
return 0;
}
You can also have variables out of scope and not enduring, such as with:
int main (void) {
// spoon is neither in scope nor enduring here ("there is no spoon")
return 0;
}
In fact, the only thing you can't have is a variable in scope but not enduring. The identifier is tied to the the storage since it makes little sense allowing a variable with no backing storage.
I'm not talking about pointers here, that's an extra level of indirection - an in-scope pointer variable always has storage for the pointer value itself, even if the thing it points to has ended, or not yet begun, its storage duration.
The fact that undefined behaviour may work in some situations in no way makes the behaviour defined, in fact that's one of the most annoying features of undefined behaviour in that it sometimes does work. Otherwise it would be much easier to detect.
In this particular case, the b
variable storage duration ends at the inner closing brace so trying to access it after that point is not wise.
The controlling part of the standard is c11 6.2.4 Storage duration of objects
(slightly paraphrased to remove unnecessary bits):
An object has a storage duration that determines its lifetime. There are four storage durations: static, thread, automatic, and allocated.
An object whose identifier is declared with no linkage and without the storage-class specifier static has automatic storage duration.
For such an object, its lifetime extends from entry into the block with which it is associated until execution of that block ends in any way.
回答2:
b
is still within a different, nested, scope that has exited and thus destroyed b
by the time you access it. So it IS undefined behavior. Everything being within the same function is immaterial.
For the purposes of variable lifetimes, you can think of "functions that have returned" as nested scopes, or vice versa.
来源:https://stackoverflow.com/questions/14116370/within-the-same-function-is-it-ub-to-access-through-indirection-a-local-variabl