throwing exceptions out of a destructor

后端 未结 16 1884
暗喜
暗喜 2020-11-22 00:23

Most people say never throw an exception out of a destructor - doing so results in undefined behavior. Stroustrup makes the point that \"the vector destructor e

16条回答
  •  面向向阳花
    2020-11-22 01:04

    We have to differentiate here instead of blindly following general advice for specific cases.

    Note that the following ignores the issue of containers of objects and what to do in the face of multiple d'tors of objects inside containers. (And it can be ignored partially, as some objects are just no good fit to put into a container.)

    The whole problem becomes easier to think about when we split classes in two types. A class dtor can have two different responsibilities:

    • (R) release semantics (aka free that memory)
    • (C) commit semantics (aka flush file to disk)

    If we view the question this way, then I think that it can be argued that (R) semantics should never cause an exception from a dtor as there is a) nothing we can do about it and b) many free-resource operations do not even provide for error checking, e.g. void free(void* p);.

    Objects with (C) semantics, like a file object that needs to successfully flush it's data or a ("scope guarded") database connection that does a commit in the dtor are of a different kind: We can do something about the error (on the application level) and we really should not continue as if nothing happened.

    If we follow the RAII route and allow for objects that have (C) semantics in their d'tors I think we then also have to allow for the odd case where such d'tors can throw. It follows that you should not put such objects into containers and it also follows that the program can still terminate() if a commit-dtor throws while another exception is active.


    With regard to error handling (Commit / Rollback semantics) and exceptions, there is a good talk by one Andrei Alexandrescu: Error Handling in C++ / Declarative Control Flow (held at NDC 2014)

    In the details, he explains how the Folly library implements an UncaughtExceptionCounter for their ScopeGuard tooling.

    (I should note that others also had similar ideas.)

    While the talk doesn't focus on throwing from a d'tor, it shows a tool that can be used today to get rid of the problems with when to throw from a d'tor.

    In the future, there may be a std feature for this, see N3614, and a discussion about it.

    Upd '17: The C++17 std feature for this is std::uncaught_exceptions afaikt. I'll quickly quote the cppref article:

    Notes

    An example where int-returning uncaught_exceptions is used is ... ... first creates a guard object and records the number of uncaught exceptions in its constructor. The output is performed by the guard object's destructor unless foo() throws (in which case the number of uncaught exceptions in the destructor is greater than what the constructor observed)

提交回复
热议问题