RAII与例外 [英] RAII vs. exceptions

查看:205
本文介绍了RAII与例外的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们在C ++中使用RAII越多,我们发现自己与非平凡的解除分配的析构函数越多。现在,释放(完成,但是你想称之为)可能会失败,在这种情况下,异常真的是让任何人在楼上知道我们的解除分配问题的唯一方法。但是,再次,抛出析构函数是一个坏主意,因为在堆栈展开期间抛出异常的可能性。 std :: uncaught_exception()可以让您知道何时发生,但不会有更多的事情,因此除非您在终止之前记录消息,否则您无法执行任何操作,除非您愿意离开你的程序在一个未定义的状态,其中一些东西被释放/最终确定,一些没有。

The more we use RAII in C++, the more we find ourselves with destructors that do non-trivial deallocation. Now, deallocation (finalization, however you want to call it) can fail, in which case exceptions are really the only way to let anybody upstairs know of our deallocation problem. But then again, throwing-destructors are a bad idea because of the possibility of exceptions being thrown during stack unwinding. std::uncaught_exception() lets you know when that happens, but not much more, so aside from letting you log a message before termination there's not much you can do, unless you're willing to leave your program in an undefined state, where some stuff is deallocated/finalized and some not.

一种方法是没有抛出的析构函数。但在许多情况下,只是隐藏了一个真正的错误。例如,我们的析构函数可能会由于抛出一些异常而关闭一些RAII管理的数据库连接,并且这些数据库连接可能无法关闭。这并不一定意味着我们可以在程序终止这一点上。另一方面,记录和跟踪这些错误并不是每种情况的解决方案;否则我们不需要开始例外。
使用无抛出的析构函数,我们也发现自己必须创建应该在销毁之前被调用的reset()函数 - 但是这只会破坏RAII的整个目的。

One approach is to have no-throw destructors. But in many cases that just hides a real error. Our destructor might, for example, be closing some RAII-managed DB connections as a result of some exception being thrown, and those DB connections might fail to close. This doesn't necessarily mean we're ok with the program terminating at this point. On the other hand, logging and tracing these errors isn't really a solution for every case; otherwise we would have had no need for exceptions to begin with. With no-throw destructors we also find ourselves having to create "reset()" functions that are supposed to be called before destruction - but that just defeats the whole purpose of RAII.

另一种方法只是让程序终止,因为这是您可以做的最可预测的事情。

Another approach is just to let the program terminate, as it's the most predictable thing you can do.

有些人建议链接异常,以便一次可以处理多个错误。但我真的从来没有真正看到在C ++中完成,我不知道如何实现这样的事情。

Some people suggest chaining exceptions, so that more than one error can be handled at a time. But I honestly never actually seen that done in C++ and I've no idea how to implement such a thing.

所以它是RAII或异常。不是吗我倾向于无抛掷的破坏者;主要是因为它保持简单(r)。但是,我真的希望有一个更好的解决方案,因为正如我所说,我们使用RAII的越多,我们越是发现自己使用不平凡的事物。

So it's either RAII or exceptions. Isn't it? I'm leaning toward no-throw destructors; mainly because it keeps things simple(r). But I really hope there's a better solution, because, as I said, the more we use RAII, the more we find ourselves using dtors that do non-trivial things.

附录

我添加了有趣的主题文章和讨论的链接:

I'm adding links to interesting on-topic articles and discussions I've found:

  • Throwing Destructors
  • StackOverflow discussion on the problems with SEH
  • StackOverflow discussion on throwing-destructors (thanks, Martin York)
  • Joel on Exceptions
  • SEH Considered Harmful
  • CLR Exception Handling which also touches on exception chaining
  • Herb Sutter on std::uncaught_exception and why it's not as useful as you think
  • Historical discussion on the matter with interesting participants (long!)
  • Stroustrup explaining RAII
  • Andrei Alexandrescu's Scope Guard

推荐答案

不得从析构函数中抛出异常。

如果异常已经在传播,那么应用程序将会终止。

You MUST NOT throw an exception out of a destructor.
If an exception is already propagating then the application will terminate.

通过终止我的意思是停止立即。堆放展开停止没有更多的析构函数被调用。所有不好的东西

By terminate I mean stop immediately. Stack unwinding stops. No more destructors are called. All bad stuff. See the discussion here.

从析构函数中抛出异常

我不遵循(不同意)你的逻辑,这导致析构函数变得更复杂。

随着智能指针的正确使用,这实际上使得析构函数更简单,因为现在所有的变量都将自动化。每个课程都会自己的小块谜题。没有脑手术或火箭科学这里。对于RAII的另一个大赢家。

I don't follow (as in disagree with) your logic that this causes the destructor to get more complicated.
With the correct usage of smart pointers this actually makes the destructor simpler as everything now becomes automatic. Each class tides up its own little piece of the puzzle. No brain surgery or rocket science here. Another Big win for RAII.

关于std :: uncaught_exception()的可能性我指向你 Herb Sutters关于为什么它不起作用的文章

As for the possibility of std::uncaught_exception() I point you at Herb Sutters article about why it does not work

这篇关于RAII与例外的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆