【问题标题】:Catching exceptions in constructor在构造函数中捕获异常
【发布时间】:2011-10-10 07:39:13
【问题描述】:

下面的示例可能会导致内存泄漏,因为在其构造函数运行期间处理异常的对象没有运行析构函数。我在哪里处理这个内存泄漏?

#include <exception>

class MyClass {

public:
       MyClass() 
       {
           c = new char[5];
           throw std::runtime_error("test");
       }

      ~MyClass ()
       {
           delete[] c;
       }

private:
    char *c;
};

int main()
{
    try 
    {
        MyClass Obj;

    } 
    catch (std::runtime_error)
    {

    }
}

【问题讨论】:

    标签: c++ exception-handling


    【解决方案1】:

    在构造函数中捕获异常,整理(释放你的内存),然后抛出异常而不发生内存泄漏。

    【讨论】:

    • 当我在构造函数中重新抛出异常而没有内存泄漏时,从未调用过析构函数。这有什么原因吗?
    • @user974191:对象构造直到构造函数的结束括号才完成。仅对完整的 Object 调用析构函数。如果构造函数没有完全执行,则对象不存在,因此不会调用析构函数。
    【解决方案2】:

    你最好使用 RAII,在这种情况下是智能指针。

    或者,您可以使用 Two Phased Construction 策略。

    您始终可以在构造函数主体内使用封闭的 try-catch 块,并为您动态分配的所有资源显式调用 delete,但想想您有 n 动态分配的资源数量的场景,它变得非常混乱在catch 中显式跟踪您需要解除分配的每个资源,在这种情况下,RAII 为您提供最佳解决方案,因为每个资源都会隐式处理自己的解除分配,您不需要承担开销跟踪每个资源。

    boost::scoped_ptrstd::tr1::scoped_ptr 适合这种情况,而不是任何原始指针。

    【讨论】:

    • 为什么要投反对票? RAII 是解决此问题的最佳方式,如果有人说否则它是不正确的。如果您觉得对 Downvote 负责,请觉得有足够的责任向我们解释为什么?如果你不能&只是觉得这是错误的,那么你没有资格投反对票,让其他人来做吧。
    • 这个解决方案是基于 C++11 相关的东西吗?
    • 也许反对票是因为建议“两阶段建设”?这听起来对我来说是个坏主意。
    【解决方案3】:

    一种方法是throw在构造函数开头的条件异常,然后分配内存。

      MyClass() 
      {
         if(<condition>)
           throw std::runtime_error("test");
         c = new char[<SIZE>];
      }
    

    另一种方法是使用特殊的try-catch() 语法封闭构造函数:

    MyClass() 
      try {
        c = new char[5];
        throw std::runtime_error("test");;
      }
      catch(std::runtime_error e) {
        delete[] c;
      }
    

    Demo.

    【讨论】:

      【解决方案4】:

      你可以在构造函数体中捕获异常,做你需要的清理,然后用throw;重新抛出异常

      也就是说,异常和手动处理内存不能很好地结合在一起。使用自动管理 c 成员内存的对象(例如 std::stringstd::vector&lt;char&gt;std::unique_ptr&lt;char[]&gt; 等)会更好。如果您正在编写像上面这样的一个类,其目的正是照顾该内存,那么您实际上只需要显式管理内存。

      【讨论】:

        猜你喜欢
        • 2013-09-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-01-20
        • 1970-01-01
        • 1970-01-01
        • 2020-01-03
        相关资源
        最近更新 更多