【问题标题】:Access Violation 'deleting' pointers at the destructor访问冲突“删除”析构函数处的指针
【发布时间】:2014-05-03 11:30:13
【问题描述】:

我的二叉搜索树析构函数如下所示。

~BSTree()
{
    if (this == nullptr || this->left == nullptr && this->right == nullptr)
    {
        return;
    }
    this->left->~BSTree();
    delete this->left;
    this->right->~BSTree();
    delete this->right;
}

在调用堆栈大约 >= 4 次调用后,我的程序在 if() 处崩溃并出现 Access Voilation Exception

我的字段只有三个:int key;,BSTree *left;BSTree *right;

this 似乎不是 NULL,但它的字段无法从内存中读取。 我如何检查他们是否可以,如果不可以remove this; 以防止异常?

【问题讨论】:

  • 不要自己调用析构函数。 delete 会为你做这件事。
  • 每个节点都涉及两次析构函数
  • this == nullptr 不是很有用。
  • Chnossos,Dieter Lücking 你是对的,我不知道delete 调用了析构函数;我以为这只是为了清除记忆。垫子,我应该用什么?
  • “我应该使用什么” - 做什么?根据定义,this 不能为空。 (只有当您的程序从较早的错误中进入未定义行为区域时,此测试才能成功,在这种情况下,无论如何所有赌注都已关闭)

标签: c++ exception memory c++11 access-violation


【解决方案1】:

多件事:

  1. 除非与放置 new 一起使用,否则不要自己调用析构函数。

  2. 根据 C++ 标准,this 不能等于 nullptr。如果是,那你的问题就更严重了。

  3. delete 已经自动调用了析构函数。

  4. delete 可以毫无问题地传递给nullptr

你的析构函数应该是这样的:

~BSTree()
{
    delete left;
    delete right;
    // possibly ...
    left = right = nullptr;
}

【讨论】:

  • 删除后还要设置this->right = nullptr;
  • @Chnossos,你能解释一下为什么“这不能等于 nullptr”吗?
  • C++ 标准说它没有意义,尽管在极少数情况下它可能发生,但它始终是一个错误。 Check this.
  • "this" 可以是 NULL / nullptr。标准是否这样说是无关紧要的。这有可能发生。只需在 NULL 指针上调用方法。只要该方法不读取/写入任何数据成员或调用任何虚函数,您就不会崩溃(疯狂的东西!)。 MFC 甚至被编写来处理这种情况(一些,不是所有的类)。
【解决方案2】:

下面的代码应该足够了,删除空指针是有效的。

~BSTree()
{
  delete left;
  delete right;
}

【讨论】:

  • 删除后还要设置this->right = nullptr;
  • 这几乎是不必要的,因为对象本身正在被删除,不会发生任何进一步的引用。
【解决方案3】:

代码应该是这样的

   ~BSTree()
   {
     if ( this->left != nullptr){
          delete this->left;
          this->left= nullptr;
     }
     if(this->right != nullptr){
       delete this->right;
       this->right = nullptr;
     }
  }

delete 操作符按顺序做两件事:

  1. 调用析构函数
  2. 取消分配内存

你不应该手动调用析构函数。还有一个常识,dest方法是在this对象上调用的,那么this怎么可以是null(可以在空对象上调用析构函数,但是这是一个错误,检查this==nullptr会没有帮助)。

【讨论】:

  • 删除后还要设置this->right = nullptr;
  • @πάνταῥεῖ,删除操作符不这样做吗?
  • @RakibulHasan 不,它没有。
  • @πάνταῥεῖ 和 Chnossos,谢谢你们。我也学到了一些东西。
  • this->right 在对象被销毁后不再存在,因此编译器无论如何都可以优化 this->right = nullptr; 行。我不明白为什么它“也应该”完成
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-12-30
  • 1970-01-01
  • 2021-04-04
  • 1970-01-01
  • 2017-08-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多