12

noexceptC++11 では、 C++03 からの変更点として、例外指定のないデストラクタが で暗黙的に宣言されます。したがって、C++03 でデストラクタからスローされていたコードは、C++11 でも正常にコンパイルされますが、そのようなデストラクタからスローしようとすると実行時にクラッシュします。

このようなコードにはコンパイル時エラーがないため、コード ベース内のすべての既存のデストラクタを として宣言する以外に、C++11 に安全に移行するにはどうすればよいnoexcept(false)でしょうか。潜在的にスローされているデストラクタをすべて検査しますが、これには本当に時間がかかり、エラーが発生しやすくなります。または、実行時にすべてのクラッシュをキャッチして修正しますが、そのようなケースがすべて見つかることは保証されませんか?

4

3 に答える 3

3

I went through this same dilemma myself once.

Basically what I concluded is that, accepting the fact that those destructors are throwing and just living with the consequences of that is usually much worse than going through the pain of making them not throw.

The reason is that you risk even more volatile and unpredictable states when you have throwing destructors.

As an example, I worked on a project once where, for various reasons, some of the developers were using exceptions for flow control in some part of the project, and it was working fine for years. Later, someone noticed that in a different part of the project, sometimes the client was failing to send some network messages that it should send, so they made an RAII object which would send the messages in its destructor. Sometimes the networking would throw an exception, so this RAII destructor would throw, but who cares right? It has no memory to clean up so its not a leak.

And this would work fine for 99% of the time, except when the exception flow control path happened to cross the networking, which then also throws an exception. And then, you have two live exceptions being unwound at once, so "bang you're dead", in the immortal words of C++ FAQ.

Honestly I would much rather have the program terminate instantly when a destructor throws, so we can have a talk with who wrote the throwing destructor, than try to maintain a program with intentionally throwing destructors, and that's the consensus of the committee / community it seems. So they made this breaking change to help you assert that your destructors are being good and not throwing. It may be a lot of work if your legacy code base has lots of hacks in it but if you want to keep developing it and maintaining it, at least on C++11 standard, you are likely better off to do the work of cleaning up the destructors.

Bottom Line:

You are right, you can't really hope to guarantee that you find all possible instances of a throwing destructor. So there will probably be some scenarios where when your code compiles at C++11, it will crash in cases that it wouldn't under C++98 standard. But on the whole, cleaning up the destructors and running as C++11 is probably going to be a whole lot more stable than just going with the throwing destructors on old standard.

于 2015-10-05T19:34:56.213 に答える