【问题标题】:Why is it possible to delete an uninitialized pointer in a destructor, but not in main? [closed]为什么可以在析构函数中删除未初始化的指针,但不能在 main 中删除? [关闭]
【发布时间】:2019-05-20 08:36:06
【问题描述】:

请检查下面 foo 函数的析构函数。如果我删除 p 指针,那么它运行良好。但是如果我在主程序中做同样的事情,那么我会得到一个错误。为什么它允许我在析构函数中这样做?

附:我知道删除指针没有意义,因为没有动态分配的内存。

class foo
{
  int* p;

public:
  ~foo()
  {
    delete p; // runs fine
    cout << "Destructor run \n";
  }
};


int main()
{

int* p;
delete p; // This will cause error "uninitialized local variable 'p' used "

foo test; // destructor runs fine at the end of the program

  return 0;
}

【问题讨论】:

  • 不是没看到问题就没事。这两种情况都是未定义的行为。
  • “我知道删除指针没有意义,因为没有动态分配的内存。” 并不是没有意义。这是因为您不允许 delete 一个不指向 newed 的指针(除了删除不做任何事情的 nullptr 之外)。虽然在这种情况下,由于指针未初始化,您甚至无法达到破坏该规则的地步。
  • 运行不正常。这是未定义的行为,您很幸运/不幸没有崩溃。
  • 删除随机指针会导致未定义的行为。有时编译器可以看穿这一点并警告你,有时他们不会。问题依然存在。
  • 编译器可以看到mainp不可能在delete p之前被初始化并且可以通知你。这很简单,但是因为在 foo p 中未初始化为成员变量,编译器稍后可以找到初始化它的构造函数或其他方法,跟踪它未初始化是模糊的,并且需要相当大多数编译器都不会费心的大量额外工作和簿记。

标签: c++ pointers destructor delete-operator


【解决方案1】:

在这两种情况下,所讨论的指针都包含一个不确定的值。访问该值,即使只是为了读取它(不要介意将它传递给delete),都会导致未定义的行为。局部变量不行,类成员也不行。碰巧编译器足够聪明,可以在局部变量的情况下捕获它。对于类成员,编译器更难弄清楚程序中没有任何东西可以给指针一个确定的值。

【讨论】:

  • 我认为这就是重点。 OP 并不清楚编译时间与运行时间,并抱怨编译器诊断的差异。
【解决方案2】:

请检查下面 foo 函数的析构函数。如果我删除 p 指针,那么它运行良好。但是如果我在主程序中做同样的事情,那么我会得到一个错误。为什么它允许我在析构函数中这样做?

这并不是说它在一个地方被允许,而在另一个地方则不允许。在这两种情况下都是未定义行为**。

真正的问题是编译器不知道foo::p 成员在~foo() 析构函数中未初始化,因为p 的声明和对delete p 的调用在不同的范围内。 foo::p 可以在 foo 对象是构造函数之后和销毁之前的任何时间分配。编译器无法验证该条件。

而在main() 内部,局部p 变量的声明和对delete p 的调用在同一范围内,编译器可以很容易地看到p 从未被初始化。

【讨论】:

    【解决方案3】:

    François Andrieux 的评论很好:

    这不是因为你没有看到问题,它很好。这两种情况都是未定义的行为。 – François Andrieux 3 分钟前

    实际上,它通过的原因是流行的编译器/平台在您分配之前将动态内存(堆)清零。因此,您的 p 恰好为 0,可以安全删除。此编译器/平台不适用于堆栈变量。

    编辑: 鉴于评论,更可能的情况是 int 变量被放入寄存器。这绝对没有初始化为任何有意义的东西。但是对象所在的堆栈内存可能(只是可能)被初始化为 0。

    但是,是的,不要依赖 UB。

    【讨论】:

    • 请注意,test 对象是堆分配的。它也是一个堆栈变量。
    • @justin 该死的好点。
    猜你喜欢
    • 1970-01-01
    • 2014-12-30
    • 2015-02-04
    • 2013-07-29
    • 1970-01-01
    • 2013-10-01
    • 2019-12-13
    • 2012-03-13
    • 2021-02-10
    相关资源
    最近更新 更多