【问题标题】:C++ basic exception questionC++基本异常问题
【发布时间】:2011-07-28 08:52:41
【问题描述】:

有人可以描述处理以下情况的正确方法是什么:

wchar_t* buffer = new wchar_t[...];

if (!something)
{
    throw std::runtime_error("Whatever");
    // Now, at this point I'm leaking memory allocated for the 'buffer'.
}

// Perform actions.
delete[] buffer;

显而易见的解决方法是:

if (!something)
{
    delete[] buffer;
    throw std::runtime_error("Whatever");
}

现在 - 还好吗? (我怀疑是这样,但谁知道呢:)


P.S我确实意识到有一个更好的方法来做到这一点 - 使用 boost::scoped_array 或简单地 std::wstring,它允许调用的析构函数释放分配的内存,只是好奇。

【问题讨论】:

    标签: c++ exception throw


    【解决方案1】:

    您的见解是正确的。模式

    Acquire some resource
    Do something
    Release resource
    

    根本上是错误的,因为Do something 可能会引发异常并泄漏资源。此外,您必须记住释放资源,这是错误的肥沃来源。

    正如您所指出的,正确的方法是始终使用析构函数释放资源的对象。这在 C++ 中的名称为 RAII

    这意味着例如。永远不要在析构函数之外使用delete,或者永远不要依赖手动关闭文件句柄,永远不要手动解锁互斥锁等。了解智能指针,并尽可能使用它们。

    请注意,某些语言(不是 C++)提供了 finally 关键字,它允许您执行指令块,而不管是否引发异常。 C++ 使用 RAII,如果您编写适当的析构函数,您永远不必担心资源释放。

    我有一个用于 C++0x 的小实用程序 there,它允许在块退出时执行任意代码,如果您与编写不佳的(或 C)库接口一次或两次。

    【讨论】:

    • +1,始终使用 std::auto_ptr、boost::shared_ptr / std::unique_ptr std::shared_ptr(均为 C++11)或类似的自动删除。
    • 我不得不不同意 RAII 意味着“永远不要手动关闭文件句柄,永远不要手动解锁互斥锁等”的断言。 RAII 声明您不必手动执行此操作,因为它保证为您完成。但是,在某些完全有效的情况下,您可能希望手动执行此操作(例如,当您需要检查失败关闭的结果时)。从不是一个强词。
    • @ToddR:即使您确实可能想要例如。要尽快关闭文件或检查失败原因,您仍然拥有 RAII 作为安全网,如果您没有达到手动关闭文件的地步,它会为您关闭文件。尽管如此,我还是更改了措辞以反映我们的讨论。
    【解决方案2】:

    catch 在哪里?如果它在同一范围内 - delete 可以在那里处理,否则您的 #2 是正确的选择。当然,假设你不想像你自己在 PS 中提到的那样以正确的方式做这件事......

    【讨论】:

      【解决方案3】:

      这取决于某物是什么。如果计算something 可以抛出异常,不,这不会很好。您必须通过使用堆栈分配的变量(在作用域的末尾被销毁)或使用各种智能指针(std 库、boost、选择)来处理您获取的每一个资源。

      【讨论】:

        【解决方案4】:

        正确的方法是使用RAII 模式。与其使用原始指针,不如将其包装在一个对象中,该对象在其析构函数中处理释放内存,例如std::wstringstd::unique_ptr

        【讨论】:

          【解决方案5】:

          如果您显式使用未包装的 new,则必须显式使用删除。所以在这种情况下,你必须捕获异常,然后调用 delete。

          正如您所说,正确的方法是将缓冲区包装在将调用其析构函数的 C++ 类中。对于一个简单的缓冲区,开销最小的类可能是 std::vector 而是一个智能指针,例如boost::scoped_ptr 也可以。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2010-11-09
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-01-18
            • 2011-04-27
            • 1970-01-01
            相关资源
            最近更新 更多