c++基本异常问题

C++ basic exception question

本文关键字:问题 异常 c++      更新时间:2023-10-16

谁能描述一下处理以下情况的正确方法?

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,它允许调用析构函数释放分配的内存,只是好奇

你的见解是对的。

模式
Acquire some resource
Do something
Release resource

从根本上是错误的,因为Do something可能会抛出异常并泄漏资源。此外,您必须记住释放资源,这是错误的丰富来源。

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

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

请注意,一些语言(不是c++)提供了finally关键字,它允许您执行指令块,而不管是否抛出异常。c++使用RAII,如果你编写了合适的析构函数,你就不必担心资源释放问题。

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

catch在哪里?如果它在相同的作用域中- delete可以在那里处理,否则您的#2是正确的选择。当然前提是你不想用正确的方法就像你自己在PS中提到的。

这取决于是什么东西。如果计算something可以抛出异常,不,那就不好了。你必须照顾你获得的每一个资源,要么使用堆栈分配的变量(在作用域结束时被销毁),要么使用各种智能指针(std库,boost,随你挑)。

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

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

正如你所说的,正确的方法是将缓冲区包装在一个c++类中,该类的析构函数将被调用。对于一个简单的缓冲区,开销最少的类可能是std::vector,但智能指针(例如boost::scoped_ptr)也可以工作。