I have a class that distributes work given by the user to several threads. Something like (simplified):
class MT {
public:
MT();
void work1(/*args*/);
void work2(/*args*/);
void work3(/*args*/);
//waits until all threads complete, returns whether the work has been completed
//successfully, throws any exceptions that have been raised in the threads.
bool is_ok();
~MT();
private:
// thread pool
}
The user uses the class as follows:
void foo()
{
MT mt;
mt.work1(/*userdata*/);
mt.work2(/*userdata*/);
mt.work1(/*userdata*/);
status = mt.is_ok();
if (status) {
mt.work3(/*userdata*/);
//...
}
//...
}
The class is never part of some object, always stored on the stack.
The Problem
I want to somehow emit any exceptions that have been raised while doing work in other threads. Unfortunately, I know whether a thread has successfully completed only after joining it. Thus, I must choose between the following two alternatives:
Join the threads in the destructor of MT and throw exceptions that arose while doing work, if any. If more than one exception has been thrown, pick the one that came from the earliest task. If the destructor is called doing stack unwinding (we can check this using std::uncaught_exception, swallow any exceptions to prevent terminate().
Instruct the user to always call is_ok before the destructor.
I think the first option is cleaner, since the user is not required to call anything. However, throwing from destructor is usually very strongly discouraged. The presented arguments are:
Throwing from destructors is dangerous, because this might happed during stack unwinding and lead to terminate().
Even if the above is addressed, throwing or not throwing depending on whether stack is being unwound is a substantial change of behavior and should be discouraged.
Exceptions signify that a postcondition have not been met. The postcondition of a destructor is resource cleanup, this must be possible in any circumstances.
Somehow I am inclined to think that the above arguments don't apply here:
I handle the stack unwinding problem properly
Due to the usage pattern, any exceptions that exit from foo means that work has been failed. Throwing or not throwing in the destructor is not a substantial change of behavior.
The postconditions of the destructor are not only resource cleanup, but also that the work has been completed successfully. Thus an exception should be appropriate.
Questions
Do you think throwing from destructor is appropriate in this case?
No, don't throw from the destructor. Call is_ok, catch and ignore. Same as close() for streams.
The user can call is_ok if they want to be sure that the work has been completed, and it will throw an exception on failure.
In practice this is rarely inconvenient. It will be if the user writes a function with multiple return points, but (unfortunately) that's a problem they just have to deal with because C++ doesn't provide a means for you to do it for them. If you think this is anti-social, well, look at what happens if you destroy a std::thread in C++11 without first either joining it or detaching it. You're beating that :-)
So, user calls is_ok on all non-error exit paths. User doesn't bother calling it when there's already an exception, because they can't deal with another one anyway. Again, this is the same as close() for streams: if you want to see errors from writing your buffered stream then you just have to close or flush explicitly.
Even if the above is addressed, throwing or not throwing depending on
whether stack is being unwound is a substantial change of behavior and
should be discouraged.
It's also not possible to do correctly, at least in C++03. I don't know whether C++11 changes anything in this respect, but std::uncaught_exception does not tell you what you need to know, as Herb Sutter explains.
From your link to cppreference.com:
Any exception thrown while std::uncaught_exception() == true calls std::terminate.
I'm pretty sure this is false. terminate is called if an exception escapes a destructor that is called as part of stack unwinding, but it isn't called just because a destructor throws and catches an exception during unwinding.
If the caller thinks they can do something useful with an exception thrown in a destructor, then they can write a helper class that calls is_ok in its destructor, and put that over your object. If you think there's something useful that your class can do with the same exception then you can do something other than merely ignore it in your destructor, but you still shouldn't allow it to leave the destructor.
Related
I know, marking a function noexcept may be useful in order to get many awesome optimizations [in some cases], such as move semantics, for example. But assume, I have a function in my code that does very critical stuff, and, if this function fails, that would mean that something so bad happened that it is impossible to recover, and the program should be terminated immediately. What if I intentionally mark such a function noexcept even if I admit the probability of exception, just to kill the program if it happens?
Something tells me this is not what it should be used for, but is it a valid use of noexcept?
This is defined behavior, that's specified in the standard. It is informally described as follows:
Whenever an exception is thrown and the search for a handler encounters the outermost block of a non-throwing function, the function std::terminate is called:
There's even a given example, over there, that does exactly that.
Note that a compiler may issue an advisory diagnostic, if it detects this situation, but this is still well-formed code.
such as move semantics
noexcept plays no role in move semantics, except that some e.g. containers try to avoid calling non-noexcept move constructors to provide exception safety guarantees that are otherwise impossible.
something so bad happened that it is impossible to recover, and the program should be terminated immediately.
If an exception isn't caught anywhere up the stack, then this is already exactly what will happen, even if the function is not marked noexcept (except that stack unwinding may or may not happen). If the exception is caught somewhere up the stack, then presumably it can be handled properly and there is no need to immediately terminate.
And if the cause of the exception itself is so critical that the program cannot continue under any circumstances, then an exception should probably not be thrown in the first place. The program should call std::abort or something similar right there at the site causing the problem.
But sure, if you think immediate termination is necessary, then mark it noexcept. I would however still explicitly catch all exceptions with a catch(...) handler in the function and call std::terminate or std::abort manually, so it is clear to a reader and to tools that this is intended behavior. (In this case the stack is unwound up to the handler.)
Is my code ill-formed if I intentionally mark a function [that I know may probably throw] noexcept to terminate immediately in case of exception?
No, letting an exception escape a noexcept function is perfectly fine. It has defined behavior: std::terminate will be called to terminate the program via the currently set terminate handler (and also may or may not unwind the stack beforehand, potentially only partially, including up to the noexcept function).
So far I never had a single warning emitted by a C++ compilers but now VS 2015 compiler seems to suddenly start complaining about this.
It seems that C++11 implicitly mark every destructor as nothrow https://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k(C4297)&rd=true
Why is that? It may be a bad idea, but I would like to understand why? And if it's not inherently bad, is there a way to override it so that destructor is not a nothrow?
P.S. I know that exceptions may be evil, but sometimes they are usefull, especially when generating crash reports from users of my app.
Destructors are called when scopes are exited. When an exception is thrown, the stack is unwound which causes scopes to be exited and destructors to be called. When an exception is thrown while another is in progress, the process is unconditionally aborted with std::terminate. That is why throwing from destructors is a bad idea and why destructors are implicitly marked noexcept (==noexcept(true))*.
If you want to throw from a destructor anyway, you can explicitly mark it noexcept(false) to override the default.
*If you throw from a function marked noexcept, std::terminate is called immediately
Why is that? It may be a bad idea, but I would like to understand why?
And if it's not inherently bad, is there a way to override it so that
destructor is not a nothrow?
Throwing exceptions in a destructor is a bad idea. The reason being during an exception stack unwinding happens i.e. destructor for all the objects on the stack is called. Now, as the stack unwinding was happening as a part of the exception, the destructor throws an exception again. You can end up having multiple exceptions and then there is no un-ambiguous way of handling these multiple exceptions. E.g. if there are two exceptions and I have a catch block for one exception and not other, shall my process terminate or the exception caught and processed further?
The other answers have done a pretty good job of explaining why throwing in a destructor is a really bad idea. Sutter & Alexandrescu explain in C++ Coding Standards (2005) "Destructors, deallocation, and swap never fail", which is another way of saying they have no preconditions. Scott Meyers gives the canonical advice in Effective C++ (3rd Ed.) (2005) "Prevent exceptions from leaving destructors" and in Effective Modern C++ (2014) "Declare functions noexcept if they won't emit exceptions".
Engineering is often about trade-offs and compromises and difficult decisions. Sometimes you might need to throw in a destructor. You better have a damn good reason, and you're probably wrong. In such a case, you can declare the destructor noexcept(false) to override the default. Then you get the C++98 behaviour. And if you want to conditionally throw if the stack is not currently being unwound by another exception, you can use std::uncaught_exception. Handling errors that occur while handling errors is a rabbit hole you would be ill advised to venture down.
If your intent is to capture a snapshot of the state of the program at the moment that the exceptional state is detected, to phone home through Google Breakpad for example, then exceptions are not a good solution for that. The automated stack unwinding will discard useful information about the state of the program. You typically want to preserve the state of the stack in your crash report, which usually means calling std::terminate or std::abort.
Because if exception is thrown before application handle a current exception program will terminate.
Probably I will get many -1 for this but I will say it anyway. You can throw a exception inside destructor. You can also do many more things that most people will say it's "evil" and everything will be ok even more it will work better then without "evil" part. But you need to know exactly what are you doing.
People have argued pretty strongly against throwing exceptions from destructors. Take this answer as an example. I wonder whether std::uncaught_exception() can be used to portably detect whether we are in the process of unwinding the stack due to some other exception.
I find myself deliberately throwing exceptions in destructors. To mention two possible use cases:
Some resource cleanup which involves flushing buffers, so that failure likely signifies truncated output.
Destruction of an object holding a std::exception_ptr which might contain an exception encountered in a different thread.
Simply ignoring these exceptional situations feels plain wrong. And chances are that by throwing an exception some exception handler might be able to provide more useful context information than if the destructor itself were writing to std::cerr. Furthermore, throwing exceptions for all failed assertions is an important part of my unit testing approach. An error message followed by an ignored error condition wouldn't work in that case.
So my question is, is it OK to throw exceptions except when another exception is being processed, or is there a reason not to do that?
To put this in code:
Foo::~Foo() {
bool success = trySomeCleanupOperation();
if (!success) {
if (std::uncaught_exception())
std::cerr << "Error in destructor: " << errorCode << std::endl;
else
throw FooOperationFailed("Error in destructor", errorCode);
}
}
As far as I can tell, this should be safe and in many cases better than not throwing an exception at all. But I'd like to verify that.
Herb Sutter has written on the subject: http://www.gotw.ca/gotw/047.htm
His conclusion is to never throw from a destructor, always report the error using the mechanism that you would use in the case where you can't throw.
The two reasons are:
it doesn't always work. Sometimes uncaught_exception returns true and yet it is safe to throw.
it's bad design to have the same error reported in two different ways, both of which the user will have to account for if they want to know about the error.
Note that for any given reusable piece of code, there is no way to know for sure that it will never be called during stack unwinding. Whatever your code does, you can't be certain that some user of it won't want to call it from a destructor with a try/catch in place to handle its exceptions. Therefore, you can't rely on uncaught_exception always returning true if it's safe to throw, except maybe by documenting the function, "must not be called from destructors". If you resorted to that then all callers would also have to document their functions, "must not be called from destructors" and you have an even more annoying restriction.
Aside from anything else, the nothrow guarantee is valuable to users - it helps them write exception-safe code if they know that a particular thing that they do won't throw.
One way out is to give your class a member function close that calls trySomeCleanupOperation and throws if it fails. Then the destructor calls trySomeCleanupOperation and logs or suppresses the error, but doesn't throw. Then users can call close if they want to know whether their operation succeeds or not, and just let the destructor handle it if they don't care (including the case where the destructor is called as part of stack unwinding, because an exception was thrown before getting to the user's call to close). "Aha!", you say, "but that defeats the purpose of RAII because the user has to remember to call close!". Yes, a bit, but what's in question isn't whether RAII can do everything you want. It can't. What's in question is whether it consistently does less than you'd like (you'd like it to throw an exception if trySomeCleanupOperator fails), or does less surprisingly when used during stack unwinding.
Furthermore, throwing exceptions for all failed assertions is an important part of my unit testing approach
That's probably a mistake - your unit testing framework should be capable of treating a terminate() as a test failure. Suppose that an assert fails during stack unwinding - surely you want to record that, but you can't do so by throwing an exception, so you've painted yourself into a corner. If your assertions terminate then you can detect them as terminations.
Unfortunately if you terminate then you can't run the rest of the tests (at least, not in that process). But if an assertion fails then generally speaking your program is in an unknown and potentially unsafe state. So once you've failed an assertion you can't rely on doing anything else in that process anyway. You could consider designing your test framework to use more than one process, or just accept that a sufficiently severe test failure will prevent the rest of the tests running. Externally to the test framework, you can consider that your test run has three possible outcomes "all passed, something failed, tests crashed". If the test run fails to complete then you don't treat it as a pass.
This is what standard says about dtors and exceptions:
15.2
(...)
The process of calling destructors for automatic objects constructed on the path from a try block to the
point where an exception is thrown is called “stack unwinding.” If a destructor called during stack unwinding
exits with an exception, std::terminate is called (15.5.1). [ Note: So destructors should generally catch
exceptions and not let them propagate out of the destructor. —end note ]
Since you asked very ambiguous question, the answer depends:
Can you throw an exception in dtor such that application won't crash? Yes, you can (in terms: it will compile and sometimes it will run correctly).
Should you throw an exception in dtor? No, you should not, because it may (and usually it will) cause you problems.
I'd say, that a need for throwing an exception from dtor is a sign of bad design. It seems, that you're doing something in your destructor, that should be done elsewhere.
I know that I shouldn't throw exceptions from a destructor.
If my destructor calls a function that can throw an exception, is it OK if I catch it in the destructor and don't throw it further? Or can it cause abort anyway and I shouldn't call such functions from a destructor at all?
Yes, that's legal. An exception must not escape from the destructor, but whatever happens inside the destructor, or in functions it calls, is up to you.
(Technically, an exception can escape from a destructor call as well. If that happens during stack unwinding because another exception was thrown, std::terminate is called. So it is well-defined by the standard, but it's a really bad idea.)
Yes.
Look at the std::fstream class in the standard library for an example.
close() could potentially throw an exception.
The destroctor can call close() but the destructor does not throw (it will swallow any exceptions).
The concept is that if the destructor calls any methods that can throw then these methods should be public. Thus if the user of your object wants to check for exceptions they can use the public methods and handle the exception. If they do not care about the exception then just let the destructor handle the problem.
Going back to the std::fstream example.
{
std::fstream text("Plop");
// Load Text.
// I don't care if the close fails.
// So let the destructor handle it and discard exceptions
}
{
// If this fails to write I should at least warn the user.
// So in this case I will explicitly try and close it.
try
{
std::ofstram password("/etc/password");
// Update the password file.
password.close();
}
catch(...)
{
Message.ShowDialog("You failed to update the Password File");
}
}
You can find some examples here: https://software.intel.com/sites/products/documentation/doclib/iss/2013/sa-ptr/sa-ptr_win_lin/GUID-D2983B74-74E9-4868-90E0-D65A80F8F69F.htm
If an exception leaves destructor during stack unwinding of another exception being propagated, then std::terminate() is called.
When no stack unwinding is in progress, an exception can leave destructor without std::terminate() getting called. However, for objects allocated on heap this will result in memory leak because "operator delete" will not be called for the object who throws exception out of its destructor. Surprisingly, the destructor of base class still gets called in this case: What happens to base class destructor if a derived class destructor throws an exception
If the exception is catched inside the destructor (so that the exception does not leave the destructor), then no problem even if stack unwinding of another exception is in progress. This case is described more deeply here: http://bin-login.name/ftp/pub/docs/programming_languages/cpp/cffective_cpp/MEC/MI11_FR.HTM
Simple answer, never allow an exception from a dtor!
The complicated answer. You only get really nailed if the exception escapes the dtor while another exception is active. The normal case for this is when you are already unwinding the stack from another exception and the object in question is destroyed. In that case if the exception escapes the dtor then std::terminate is called, note you can put in your own handler for std::terminate by calling std::set_terminate. The default implementation of std::terminate is to call abort.
To complicate things more, most functions that want to make any guarantee about their exception safety, mainly the basic guarantee or the strong guarantee, rely on the underlying types to themselves not throw in their dtor*
The real question is, what state would your program be in when this error occurs? How can you recover? Where should this recovery be handled? You need to look at your specific case and work these issues out. Sometimes it's just fine to catch the exception and ignore it. Other times you need to raise some red flags.
So the answer is: it allowed by C++ to throw an exception in a dtor, but you shouldn't ever allow it to escape.
*Here's a brief synopsis of the exception guarantees (here's a much longer article)
Recap: Briefly define the Abrahams exception safety guarantees (basic,
strong, and nothrow).
The basic guarantee is that failed
operations may alter program state,
but no leaks occur and affected
objects/modules are still destructible
and usable, in a consistent (but not
necessarily predictable) state.
The strong guarantee involves
transactional commit/rollback
semantics: failed operations guarantee
program state is unchanged with
respect to the objects operated upon.
This means no side effects that affect
the objects, including the validity or
contents of related helper objects
such as iterators pointing into
containers being manipulated.
The nothrow guarantee means that
failed operations will not happen. The
operation will not throw an exception.
You may find this page from C++ FAQ Lite to be informative. The basic answer is, "don't do it." Where exactly do you plan to catch this exception? Whatever you plan on doing when you catch that exception, just do it with a function call instead or something (e.g. log it or set a flag to warn the user or whatever). Throwing exceptions from the destructor runs the risk of causing your entire program to terminate.
I know destructor shouldn't not throw exception.
http://www.parashift.com/c++-faq-lite/dtors.html#faq-11.13
I have the following code :
~a()
{
cleanup();
}
// I do not expect exception being thrown in this function.
// If exception really happen, I know that it is something not recoverable.
void a::cleaup()
{
delete p;
}
In my static source code analysis, it complains that I shall call the cleanup function in this way :
~a()
{
try {
cleanup();
}
catch(...) {
// What to do? Print out some logging message?
}
}
// I do not expect exception being thrown in this function.
// If exception really happen, I know that it is something not recoverable.
void a::cleaup()
{
delete p;
}
I am not sure whether this is a good practice, to place try...catch block in destructor, whenever it calls functions. As :
(1) If cleanup function able to throw exception, I know something bad had happened. I prefer it to be fail-fast. That is, just let the whole system crash, and let the programmer debugs it.
(2) Overhead occur while entering and exiting try...catch block.
(3) The code look cumbersome, with a lot of try...catch block around classes' destructor.
I may miss out some other points, why try...catch block should be in place.
Thanks.
Since delete won't throw, neither will cleanup and as such there is no need to put the call in try-catch.
Since your static analysis tool is probably having a hard time figuring that out, perhaps you could help it out (it's only a guess though) by declaring cleanup as no-throw.
void cleanup() throw();
Maybe you can be more precise about your cleanup function. Does the cleanup() function throw an exception intentionally, if only in very rare circumstances? Then you should definitely handle the case in your destructor because, even if rare, exception-throwing is expected behavior of cleanup().
At the very least, your exception handling code could leave your program in a well-defined state that would allow you to end your program gracefully.
Or do you mean cleanup() may throw e.g. an OutOfMemoryException or another runtime exception that you never handle anywhere else? Then I would omit the exception handling in the destructor as well. In such unusual circumstances, your application could probably not run its error handling code anyway. You should do everything possible to make sure even such an exceptions gets reported or logged properly.
Edit:
Now that you have shown the implementation of cleanup, Neil has already answered your question. delete p must not throw, hence a::cleanup will not throw as long as p's destructor does not throw.
Surely the issue is really in the destructor of p. When, in cleanup(), you say
delete p;
delete itself cannot throw, therefore the exception must comne from p's destructor. It is in that destructor you need to worry about using a try block, not the one for a.
There's not usually any point in throwing an error due to memory allocation or deletion. It either works or not, and you can spend a ton of work handling silly errors without getting any benefit.
You might want to do this in specific cases but it's nor done much in practice and when there's question you usually want to use debugger or more full instrumentation.
Fundamentally, it is not safe to throw an exception whilst already handling an exception.
If your destructor is being called whilst the stack is unwinding, and another exception is thrown, then your thread can be terminated immediately on some systems such as Symbian; that your code was planning to catch the exception won't stop that termination - your code won't even be called. Your thread certainly will be terminated if your exception escapes the destructor.
So try {} catch(...) {} in a destructor is not portable and is certainly tricky.
The sound advice is never call code that could throw an exception in cleanup code such as destructors and any function that might be called from a destructor, such as 'cleanup()', 'close()' or 'release_something()'.
The original poster also queries the performance of try-catch. Early in the adoption of C++ exceptions, exception handling code was reasonably expensive; these days, your compiler almost certainly uses zero-cost exceptions, which means that an exception not thrown adds no runtime performance penalty to the code (but of course does slightly increase the binary size of the program).
I never use this, but exception safety purists will say that your cleanup() function may throw without you expecting it. So this pattern is a technique for extra safety.
However, a cleanup function should not throw in the first place. So I would put any exception handling inside cleanup(), not in the destructor itself.