【问题标题】:How is memory allocated in constructor released when the constructor throws an exception?当构造函数抛出异常时,构造函数中分配的内存如何释放?
【发布时间】:2019-08-12 08:28:12
【问题描述】:

以下是我的示例代码。基类有一个 A 类指针,使用 new 运算符从堆分配内存。我明确地抛出了一个异常。由于我没有在 *ptr 上调用 delete,因此不会释放 new 分配的内存。既然对象还没有完全构造好,怎么释放内存呢?

#include <iostream>

using namespace std;
class A
{
    public:
    A()
    {
        cout<<"A::ctor"<<endl;
    }
    ~A()
    {
        cout<<"A::Dctor"<<endl;
    }
};
class Base
{
    public:
    A *ptr;
    Base()
    {
       ptr = new A();
        cout<<"Base::Ctor"<<endl;
        throw std::exception();
    }
    ~Base()
    {
        delete ptr;
        cout<<"Base::Dtor"<<endl;
    }
};

int main()
{
    try{
        Base bobj;

    }
    catch(exception e)
    {

        cout<<e.what();
    }

    return 0;
}

当 Base 构造函数抛出异常时,控件转到 catch 块并处理异常。但是ptr = new A();分配的内存是怎么释放的呢?

现在我知道使用智能指针可以解决问题。但是在 C++11 之前,这种情况是如何处理的。

另外,我想知道我们如何关闭文件处理程序的一个文件处理程序在构造函数中打开并且构造函数有异常?

Base()
{
 ofstream myfile;
 myfile.open("myfile.txt");
 ..........
 throw std::exception();
}

~Base()
{
  myfile.close();
}

【问题讨论】:

  • "我想知道我们如何关闭文件处理程序的文件处理程序在构造函数中打开并且构造函数有异常?" try { ... } catch() { myfile.close(); throw; }

标签: c++ exception constructor


【解决方案1】:

ptr 关联的内存永远不会被释放!

是的,这一直是个问题。

在 C++11 之前,您可以构建自己的智能指针类(例如,使用 Boost 中的智能指针类),或者在引发异常之前注意delete。将ptr 放在基类中也是一种选择:基类构造函数将在派生构造函数的函数体到达之前完成。

【讨论】:

  • 所以你的意思是说在 C++11 之前这种内存泄漏从未解决?我们这里没有继承。
  • @arjunjawalkar:他们使用的是我在最后一段中提到的技术。
  • 正如你所说的“在抛出异常之前删除”,说我们没有明确抛出异常,但由于某种原因发生了编程中常见的异常,我们无法确定在哪里删除分配的内存。
  • @arjunjawalkar:那么使用智能指针是一个明显的解决方法。例如。 std::auto_ptr(在 C++11 中弃用后,现在在 C++17 中删除),尽管它有奇怪的复制语义。
  • @arjunjawalkar 你可能想看看RAII。几十年来,智能指针(以及一般的 RAII)一直是处理 C++ 资源管理的标准技术。 C++11 没有引入这些想法,它只是为我们提供了使它们变得更好的工具……
猜你喜欢
  • 2014-04-03
  • 2013-11-10
  • 1970-01-01
  • 2011-11-04
  • 1970-01-01
  • 2012-10-28
  • 2012-04-30
  • 1970-01-01
  • 2012-04-15
相关资源
最近更新 更多