【问题标题】:There is a variable in scope. Is it undefined behavior to use this variable address outside of scope?范围内有一个变量。在范围之外使用这个变量地址是未定义的行为吗?
【发布时间】:2020-06-18 10:03:15
【问题描述】:

这是一个简单的例子。

void func()
{
    int* p = nullptr;
    if(p == nullptr)
    {
        int n;
        p = &n;
    }
    *p = 10; // undefined behavior??
}
int main()
{
    func();
}

没有编译警告(visual studio 2019),这样使用“* p = 10”是“未定义行为”吗?

它会因编译器、调试或发布而异吗?

【问题讨论】:

  • 简短回答:是的
  • 是未定义的行为吗?”是的。
  • 程序执行的操作可能因编译器和月相而异,但始终未定义
  • @NikosC.:呸,我以为我明天有一个巨大的重构工作。
  • fwiw,编辑并没有改变问题或答案的任何内容。当您的代码具有 UB 时,编译器不需要发出警告或错误

标签: c++ memory scope


【解决方案1】:

是的,取消引用 p 的行为未定义。

还要注意,即使 读取 p 所指向的对象超出范围时,其行为也是有问题的:此时它是一个无效的指针值,并且正式地读取p 的行为是实现定义的,其中可能包括系统生成的运行时错误。

后一点经常被忽视。

【讨论】:

  • 很容易误读您的答案。我首先认为“解除引用和阅读”是相同的,因为我混淆了 n 和 p。也许你可以写:读取 p 已经是未定义的行为,即使没有取消引用它。这将按时间顺序提及动作,这样更容易理解。
  • 在指向的对象被销毁后,指针的行为不像未初始化,即作为一个不确定值。相反,它将成为一个无效的指针值。评估 indeterminate values 具有未定义的行为,评估 invalid pointer values 具有实现定义的行为,因此在实践中它可能在大多数平台上都可以。 (理想情况下,应该能够在编译器文档中找到该行为,但我不确定是否有任何编译器正确记录了这一点。)请参阅eel.is/c++draft/basic#stc-4DR 616
  • @walnut 有趣的区别:可能是因为指向超出范围的对象的指针的值至少具有有效的地址格式,特别是它不是陷阱值。
猜你喜欢
  • 2021-08-18
  • 1970-01-01
  • 1970-01-01
  • 2022-08-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-08-19
  • 1970-01-01
相关资源
最近更新 更多