【问题标题】:Memory deallocation and exceptions内存释放和异常
【发布时间】:2010-08-15 07:05:23
【问题描述】:

我有一个关于内存释放和异常的问题。当我使用 delete 删除在堆上创建的对象时。如果在此删除之前发生异常,是内存泄漏还是此删除将执行?

【问题讨论】:

标签: c++ exception


【解决方案1】:

在你描述的情况下,内存会泄漏。

避免这个问题的两个技巧:

  • 使用智能指针,不会遇到同样的问题(首选解决方案)
    --> 在栈上构造的智能指针,因此无论如何都会调用其析构函数,并在析构函数中提供指向内容的删除

  • 使用try/catch语句,同时删除catch语句中的项

【讨论】:

    【解决方案2】:

    这取决于delete 在哪里。如果它在捕获异常的catch 内,它可能会调用。

    try {
        f();  // throws
    } catch( ... ) {
        delete p;  // will delete
    }
    

    如果在捕获异常的catch 之后并且catch 没有从函数返回(即允许在catch 块之后继续执行流程),则可能会调用delete。

    try {
        f();  // throws
    } catch( ... ) {
        // execution proceeds beyond catch
    }
    delete p;  // will delete
    

    如果delete 不在catch 块中或在允许继续执行的catch 块之后,则delete 将不会调用。

    try {
        f();  // throws
        delete p;  // will not delete
    }  // ...
    

    如您所想,在上述前两种情况下,如果在 delete 之前有一个 throw,则不会调用 delete:

    try {
        f();  // throws
    } catch( ... ) {
        g();  // throws
        delete p;  // will not delete
    }
    

    【讨论】:

    • 请注意,异常很好,因为您不必在调用堆栈中的每个函数中捕获它们。它们可以在一个“外部”水平上咳嗽。如何释放内部函数中分配的内存?例如,如果函数 f() 抛出异常,则会分配内存。在 f() 中捕获异常并释放内存然后将其重新扔到调用堆栈中的下一级是否是个好主意?
    【解决方案3】:

    它不会被调用。这就是为什么鼓励您查看 RAII。见Stroustrup

    【讨论】:

      【解决方案4】:

      我们还必须确保“异常”真正意味着可以被 try/catch 捕获的 C++ 异常。系统中还有其他 C++ try/catch 无法捕获的异常(例如除以 0)。

      在这种情况下(超出 C++ 标准的范围),“delete”也不会被执行,除非这些异常被捕获并且处理程序适当地显式调用“delete”。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-07-29
        • 2010-11-21
        • 1970-01-01
        • 2011-01-10
        • 2015-02-15
        相关资源
        最近更新 更多