问题描述
在第二个右大括号之后,b
只能通过 a
间接访问.
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;
}
既然 b
不在范围内,这是 UB 吗?我知道从已经返回的函数中取消引用指向非静态局部变量的指针是 UB,但在这种情况下,所有内容都在同一个函数中.
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.
这是 C++ 中的 UB,但我不确定 C.
This is UB in C++, but I'm not sure about C.
推荐答案
是的,访问任何已达到其生命周期结束的变量是未定义的行为.范围和此处的存储持续时间略有不同.范围更像是变量标识符什么时候可见?"并且存储持续时间是变量本身什么时候存在?".
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;
}
或超出范围但持久:
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.
我不是在这里谈论指针,这是一个额外的间接级别 - 范围内的指针变量总是存储指针值本身,即使它指向的东西to 已结束或尚未开始其存储期限.
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.
在这种特殊情况下,b
变量存储持续时间在内部右大括号处结束,因此在该点之后尝试访问它是不明智的.
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.
标准的控制部分是c11 6.2.4 对象的存储持续时间
(稍微解释以删除不必要的位):
The controlling part of the standard is c11 6.2.4 Storage duration of objects
(slightly paraphrased to remove unnecessary bits):
对象具有决定其生命周期的存储持续时间.有四个存储持续时间:静态、线程、自动和分配.
其标识符声明为没有链接且没有存储类说明符 static 的对象具有自动存储持续时间.
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.
这篇关于在同一个函数中,UB 是否可以通过间接访问访问不在作用域内的局部变量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!