【问题标题】:Constructor finishes by throwing an exception ? Is there a memory leak?构造函数通过抛出异常结束?有内存泄漏吗?
【发布时间】:2014-11-15 17:57:39
【问题描述】:

我正在浏览this 文章 它指出

注意:如果构造函数通过抛出异常结束,内存 与对象本身相关联的东西被清理——没有内存 泄漏。例如:

void f()
{
X x; // If X::X() throws, the memory for x itself will not leak
Y* p = new Y(); // If Y::Y() throws, the memory for *p itself will not leak
}

我很难理解这一点,如果有人能澄清这一点,我将不胜感激。我尝试了以下示例,该示例表明如果构造函数内部出现异常,则不会调用析构函数。

struct someObject
{
    someObject()
    {
      f = new foo();    
      throw 12;
    }
    ~someObject()
    {
        std::cout << "Destructor of someobject called";
    }

    foo* f;
};

class foo
{
public:
    foo()
    {
            g = new glue();
            someObject a;
    }
    ~foo()
    {
        std::cout << "Destructor of foo";
    }
 private:
  glue* g;
};


int main()
{
    try
    {
        foo a;
    }
    catch(int a)
    {
        //Exception caught. foo destructor not called and someobject destrucotr not called.
       //Memory leak of glue and foo objects
    }
}

我该如何解决这个问题?

对于更新可能造成的不便,我们深表歉意。

【问题讨论】:

  • 没有调用析构函数,因为对象从未正确构造。

标签: c++ exception memory-leaks constructor


【解决方案1】:

"...不会调用析构函数。"

由于对象还没有被认为是构造的,所以在构造函数异常失败后,析构函数将不会被调用。

对象分配和构造(仅仅是破坏)是不同的东西。

在抛出异常之前使用new() 分配的任何对象都会泄漏。

您不应该自己管理这些资源,除非您真的、真的、真的需要它,并且 100% 确定自己在做什么。

而是为来自standard dynamic memory management library 的类成员使用合适的智能指针。

【讨论】:

  • 但不会有胶水和 foo 对象的内存泄漏
  • 感谢您解决这个问题。再次对更新可能造成的不便表示歉意。
【解决方案2】:

当构造函数抛出时,不会调用析构函数。当一个 在构造函数中抛出异常有几件事 您应该注意正确处理资源 在中止的构造中可能发生的分配 对象:

  • 将不会调用正在构造的对象的析构函数。
  • 将调用该对象类中包含的成员对象的析构函数
  • 正在构造的对象的内存将被释放。

【讨论】:

  • 欢迎来到社区!您正在使用引用标记并链接到您的答案中的当前问题。可能不需要链接和引用。您可以通过答案下方的“编辑”链接编辑您的答案。
  • 应该澄清的是,类成员的析构函数仅对在抛出异常之前完全构造的成员调用。在构造函数体内使用new 分配的成员必须手动为deleted,因为它们的析构函数不会被自动调用。这意味着捕获异常,释放内存,然后重新抛出异常。或者使用智能包装器来保存分配的内存,直到构造函数准备好正常退出。
猜你喜欢
  • 2019-08-19
  • 2020-11-02
  • 2015-08-29
  • 2018-11-18
  • 1970-01-01
  • 2021-07-07
  • 2014-12-15
  • 2014-03-15
  • 1970-01-01
相关资源
最近更新 更多