C++基本异常问题

发布于 2024-11-26 21:13:35 字数 619 浏览 4 评论 0原文

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

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

Could someone please describe what's the correct way to handle the following situation:

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;

The obvious way to solve it means something like:

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

Now - is it fine? (I suspect so, but who knows :)


P.S I do realize that there is a much better way to do it - using, boost::scoped_array or simply std::wstring, which allows the destructors called to release the allocated memory, just being curious.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

森末i 2024-12-03 21:13:35

你的见解是正确的。该模式

Acquire some resource
Do something
Release resource

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

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

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

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

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

Your insight is right. The pattern

Acquire some resource
Do something
Release resource

is fundamentally wrong, since Do something can potentially throw an exception and leak the resource. Moreover, you have to remember to release the resource, which is a fertile source of errors.

The correct way, as you point, is to always use an object whose destructor releases the resource. This goes by the name of RAII in C++.

This means eg. never using delete outside destructors, or never rely on manually closing file handles, never unlock mutexes manually, etc. Learn about smart pointers, and use them whenever you can.

Note that some languages (not C++) provide a finally keyword, which permits you to execute a block of instructions irrespectively of whether an exception is thrown. C++ uses RAII, and you should never be concerned with resource release if you write proper destructors.

I have a little utility there for C++0x which allows execution of arbitrary code at block exit, should you interface once or twice with poorly written (or C) libraries.

星光不落少年眉 2024-12-03 21:13:35

陷阱在哪里?如果它在相同的范围内 - 可以在那里处理删除,否则你的#2是正确的选择。当然,假设你不想像你自己在 PS 中提到的那样以正确的方式去做......

Where's the catch? If it's in the same scope - the delete can be handled there, otherwise your #2 is the right option. That assuming of course that you don't want to do it the right way as you yourself mentioned in the PS...

眼波传意 2024-12-03 21:13:35

这取决于某物是什么。如果计算某事可能会抛出异常,不,那就不好了。你必须照顾你获得的每一个资源,要么使用堆栈分配的变量(它们在作用域结束时被销毁),要么使用各种类型的智能指针(std库,boost,任你选择)。

It depends on what something is. If computing something could throw an exception, no, it wouldn't be fine. You have to take care of every resource that you acquire, either by using stack allocated variables (which are destroyed at the end of the scope) or by using smart pointers of various kinds (std library, boost, take your pick).

夜还是长夜 2024-12-03 21:13:35

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

The correct way is to use the RAII pattern. Rather than using a raw pointer, you should wrap that in an object that handles freeing the memory in its destructor, such as a std::wstring or std::unique_ptr.

穿越时光隧道 2024-12-03 21:13:35

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

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

If you explicitly use an unwrapped new you will have to explicitly use a delete. So in this case you have to catch the exception and then call delete.

As you say the correct way is to wrap the buffer in a C++ class whose destructor will be called. For a simple buffer the class with the least overhead is probably std::vector but a smart pointer e.g. boost::scoped_ptr will work as well.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文