使用指针的合法遗留代码突然变为UB

Sla*_*ica 3 c++ language-lawyer c++11 c++98

假设我们有来自C++ 98的遗留代码:

bool expensiveCheck();

struct Foo;

bool someFunc()
{
    Foo *ptr = 0;
    if( expensiveCheck() )
        ptr = new Foo;

    // doing something irrelevant here
    ...
    if( ptr ) {
        // using foo
    }
    delete ptr;
    return ptr; // here we have UB(Undefined Behavior) in C++11
}
Run Code Online (Sandbox Code Playgroud)

所以基本上这里的指针用于保持动态分配的数据并同时将其用作标志.对我来说它是可读代码,我相信它是合法的C++ 98代码.现在根据这个问题:

删除后在c ++中的指针

删除后指针本身会发生什么?

这段代码在C++ 11中有UB.这是真的吗?

如果是,请记住另一个问题,我听说委员会付出了巨大努力,不破坏新标准中的现有代码.如果我在这种情况下没有弄错,这不是真的.是什么原因?这样的代码是否已经被认为是有害的,所以没有人关心它会被打破?他们没有考虑后果?这种优化是如此重要?别的什么?

Igo*_*nik 7

您的示例也展示了C++ 98下的未定义行为.从C++ 98标准:

[basic.stc.dynamic.deallocation]/4如果给标准库中的释放函数赋予的参数是一个不是空指针值的指针(4.10),则释放函数将释放指针引用的存储,渲染使所有指针都无效,这些指针指的是解除分配的存储的任何部分.使用无效指针值(包括将其传递给释放函数)的效果是未定义的.33)

脚注33)在某些实现中,它会导致系统生成的运行时故障.

  • @ L.ScottJohnson这是值得怀疑的.首先,该脚注的C++ 14版本写道:"某些实现可能会定义复制无效指针值会导致系统生成的运行时错误." 实际上,我记得在某个地方读到存在或退出的架构,其中只是将无效指针加载到CPU寄存器中可能会陷阱.它具有专用的地址寄存器(与数据不同),并使用段/偏移寻址,其中段指向段表.如果表条目无效,则CPU引发异常. (3认同)
  • "安全派生"仅与具有严格指针安全性的实现相关,这是一个空集. (2认同)