【问题标题】:Operator new/delete & destructors运算符 new/delete 和析构函数
【发布时间】:2011-06-11 20:46:03
【问题描述】:

所以我是一个试图掌握 operator new 的初学者。我的析构函数有什么问题?

class arr{
public:
    arr(){
        pool=::operator new(100*sizeof(double));
    }
    ~arr(){
        ::operator delete(pool);
    }
    void* pool;
};

int main()
{
    arr a;
    a.~arr(); //If I comment this out it's ok.

    void* pool2=::operator new(100*sizeof(double)); //Works
    ::operator delete(pool2); //Fine.

    system("pause");
    return 0;
}

离开a.~arr(); in 给了我这个错误:

调试断言失败!文件:dbgdel.cpp 行:52

表达式:_BLOCK_TYPE_IS_VALID(pHead->nBlockUse)

我不明白为什么 pool2 可以正常工作,但使用该类会给我带来问题。此外,该错误仅在系统“暂停”后才弹出,即在调用 a.~arr() 之后???

谢谢!

【问题讨论】:

    标签: c++ visual-c++ memory-management destructor


    【解决方案1】:

    好吧,乍一看,您不应该显式调用析构函数。而是使用作用域强制超出作用域并调用析构函数。

    int main()
    {
        {
            arr a;
        } //This calls destructor of a
    
        //Rest of code
    }
    

    否则,a 的析构函数会被调用两次:一次是在您调用它时,另一次是在 a 超出范围时。

    编辑:

    来吧。

    http://www.parashift.com/c++-faq-lite/dtors.html

    【讨论】:

    • 另请阅读下面 sbi 的答案 - 如果您不声明复制构造函数和赋值运算符以确保 arr 实例的多个副本不会尝试删除相同的内存,则会遇到问题。
    【解决方案2】:

    问题是您在a (a.~arr()) 上显式调用了析构函数,而a 退出时,析构函数已经被自动调用 main() 末尾的范围。当第二次调用析构函数时,在一个已经被销毁的对象上调用它。从技术上讲,这会导致 Undefined Behavior(这是一种表示根据 C++ 标准任何结果都可以的方式)。在实践中,这段代码可能只是再次执行析构函数,将存储在曾经是a.pool的内存位置中的地址传递给::operator delete()(可能是也可能不是构造函数存储在那里的地址),这被调试运行时。

    如果你想在main() 中间删除a,你应该做的是引入一个额外的范围:

    int main()
    {
      {
        arr a;
      } //a will be deleted here
    
      // rest of main
    
    }
    

    另一种方法是不使用自动对象,而是使用动态对象,您可以为其设置生命周期。


    但是你的代码还有另一个问题,你没有问,但我仍然觉得有必要指出:

    你的类迫切需要一个复制构造函数和一个赋值运算符。 (至少,声明它们private 以禁止复制。)根据Rule Of Three,您需要一个析构函数这一事实应该提示您也需要其他两个。
    您可以通过不尝试手动管理动态分配的内存来避免所有麻烦。而是使用为您执行此操作的类型:

    class arr{
    public:
        arr() : pool(100*sizeof(double)) {
    
        }
        // ~arr() // not needed any longer
        std::vector<char> pool;
    };
    

    【讨论】:

      【解决方案3】:

      您不需要为在堆栈上创建的对象调用析构函数。变量“a”在堆栈中,超出范围时会自动删除。

      【讨论】:

      • 不仅仅是你“不需要”;它是无效的。
      猜你喜欢
      • 2023-03-27
      • 1970-01-01
      • 1970-01-01
      • 2012-08-04
      • 2014-03-26
      • 1970-01-01
      • 2014-01-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多