【问题标题】:How to Overcome Memory Leak while throwing exception from constructor?从构造函数抛出异常时如何克服内存泄漏?
【发布时间】:2020-11-02 19:56:16
【问题描述】:

这个程序是否有内存泄漏,如果是,那么如何解决这个问题??

#include<iostream>
using namespace std;
class A
{
    double a,b;
  public:
    A(double X,double Y)
    {
        try
        {
        a = X;
        b = Y;
            if(b==0)
            throw b;
            else
            cout <<"Division:"<<a/b<<endl;
        }
        catch (double z)
        {
            throw z;
        }
    }
      ~A()
        {
            cout<<"Object Destroyed"<<endl;
         }
 }; 
 int main()
 {
   try
   {
    A object(10,2);
    A object1(4,2);
    A object2(4,0);
   }
  catch(double a)
  {
    cout<<"Zero:"<<a<<endl;
  }
  return 0;
  }

对于 Object2,为什么不调用析构函数,如果有任何从构造函数抛出异常的最佳方法是什么?

【问题讨论】:

  • 我没有看到任何内存泄漏。
  • object2 永远不会被构造,所以没有什么可以破坏
  • catch (double z) { throw z; } 似乎毫无意义。如果这就是你所做的一切,为什么还要使用try / catch
  • @RoseAhmed “为什么不为 object2 调用析构函数??” - 因为对象从未完全构造,构造函数抛出异常,所以没有对象可以调用析构函数。
  • @RoseAhmed: objectobject1 将被完全构造和破坏。 object2 不会完成构造,由于异常,所以不调用析构函数。虽然没有内存泄漏。 object2 可能存在内存泄漏的风险,但解决方案是使用 RAII 成员,不要自己使用 new

标签: c++ c++11


【解决方案1】:

所以你没有做任何动态分配,它都是基于堆栈的。所以它会清理得可以接受。如您所知,您的析构函数没有做任何有用的事情。

但请注意,构造函数中的 throw 不会调用相应的析构函数,并且如果 object2 /had/ 的构造函数在它抛出之前完成了任何分配(您想在析构函数中清理),那么它很容易泄漏。但请注意,具有构造函数和基类的成员会被破坏。规则是,对于每一个构造/完成/的子对象,都会调用对应的析构函数,但是通过在这个构造函数的中间抛出,那么它没有完成,它对应的析构函数也不会被调用。

这是在构造函数中使用 throw 的困难 - 并且需要使用 RAII 缓冲区对所有内容进行防弹或清理。

这里有更多关于什么被破坏和不被破坏的信息:What destructors are run when the constructor throws an exception?

【讨论】:

    猜你喜欢
    • 2015-08-29
    • 2019-08-19
    • 2018-11-18
    • 2014-11-15
    • 2014-12-15
    • 2014-03-15
    • 2013-08-21
    • 2011-11-04
    • 1970-01-01
    相关资源
    最近更新 更多