C ++基本异常问题

时间:2011-07-28 08:52:42

标签: c++ exception throw

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

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");
}

现在 - 好吗? (我怀疑如此,但谁知道:)


PS 我确实认识到有更好的方法 - 使用boost::scoped_array或简单地std::wstring,它允许被调用的析构函数释放已分配的内存,只是好奇。

5 个答案:

答案 0 :(得分:8)

你的见解是正确的。模式

Acquire some resource
Do something
Release resource

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

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

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

请注意,某些语言(不是C ++)提供了finally关键字,它允许您执行一个指令块,而不管是否抛出异常。 C ++使用RAII,如果编写适当的析构函数,就不应该关注资源释放。

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

答案 1 :(得分:0)

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

答案 2 :(得分:0)

这取决于什么是什么。如果计算something可以抛出异常,不行,那就不行了。您必须通过使用堆栈分配的变量(在范围的末尾销毁)或使用各种智能指针(std库,提升,选择)来处理您获得的每个资源。

答案 3 :(得分:0)

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

答案 4 :(得分:0)

如果明确使用未包装的新内容,则必须明确使用删除。因此,在这种情况下,您必须捕获异常,然后调用delete。

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