Way for C++ destructor to skip work when specific exception being thrown? - c++

I have an object on the stack for which I wish its destructor to skip some work when the destructor is being called because the stack is being unwound due to a specific exception being thrown through the scope of the object on the stack.
Now I could add a try catch block inside the scope of the stack item and catch the exception in question and notify the stack object to not run the work to be skipped an then rethrow the exception as follows:
RAII_Class pending;
try {
doSomeWorkThatMayThrowException();
} catch (exceptionToSkipPendingDtor &err) {
pending.notifySkipResourceRelease();
throw;
}
However, I'm hoping there is a more elegant way to do this. For example imagine:
RAII_Class::~RAII_Class {
if (detectExceptionToSkipPendingDtorBeingThrown()) {
return;
}
releaseResource();
}

You can almost do this with std::uncaught_exception(), but not quite.
Herb Sutter explains the "almost" better than I do: http://www.gotw.ca/gotw/047.htm
There are corner cases where std::uncaught_exception() returns true when called from a destructor but the object in question isn't actually being destroyed by the stack unwinding process.
You're probably better off without RAII because it doesn't match your use case. RAII means always clean up; exception or not.
What you want is much simpler: only release resource if an exception is not throw which is a simple sequence of functions.
explicitAllocateResource();
doSomeWorkThatMayThrowException();
explicitReleaseResource(); // skipped if an exception is thrown
// by the previous function.

I would do it the other way around - explicitly tell it to do its work if no exception was thrown:
RAII_Class pending;
doSomeWorkThatMayThrowException();
pending.commit(); // do or prepare actual work

This seems to circumvent the main reason to use RAII. The point of RAII is that if an exception happens in the middle of your code you can still release resources/be destructed properly.
If this isn;t the semantic you want, then don't use RAII.
So instead of:
void myFunction() {
WrapperClass wc(acquireResource());
// code that may throw
}
Just do:
void myFunction() {
Resource r = acquireResource();
// code that may throw
freeResource(r);
}
If the code in the middle throws, the resource won't be freed. This is what you want, rather than keeping RAII (and keeping the name) but not implementing RAII semantics.

Looks like bool std::uncaught_exception(); does the trick if you want to have this behavior for every exception, not just special ones!

You can do without a try-catch:
RAII_Class pending;
doSomeWorkThatMayThrowException(); // intentional: don't release if throw
pending.releaseResource();
Alternatively, you can try a little harder with RAII:
struct RAII_Class {
template<class Op>
void execute(Op op) {
op();
releaseResources();
}
private:
void releaseResources() { /* ... */ }
};
int main(int argc, char* argv[])
{
RAII_Class().execute(doSomeWorkThatMayThrowException);
return 0;
}

Although it would be a kludge at best, if you own the code for the exception class you're interested in, you could add a static data member to that class (bool) that would be set to "true" in the constructor for objects of that class, and false in the destructor (might need to be an int that you increment/decrement instead). Then in the destructor of your RAII class, you can check std::uncaught_exception(), and if true, query the static data member in your exception class. If you get true (or > 0) back, you've got one of those exceptions--otherwise you ignore it.
Not very elegant, but it would probably do the trick (as long as you don't have multiple threads).

I found this website with an interesting discussion about std::uncaught_exception() and an alternative solution to your question that seems much more elegant and correct to me:
http://www.gotw.ca/gotw/047.htm
// Alternative right solution
//
T::Close() {
// ... code that could throw ...
}
T::~T() /* throw() */ {
try {
Close();
} catch( ... ) {
}
}
In this way you're destructor does only one thing and you're protected against throwing an exception during an exception (which I assume is the problem you're trying to solve).

Related

C++: How to catch exceptions thrown from constructors?

I have a class, call it A, whose constructor takes some input arguments, and may throw an exception if they are incompatible for constructing that object. In my main code, I construct an object of type A as follows:
A my_obj(arg1,arg2,arg3);
and use it. Obviously if the constructor fails and throws the exception, the execution of the program will be terminated after printing out an 'unhandled exception' message.
I, however, would like to give the user more information in this case and tell him/her why the exception has been thrown. So, I need a way to catch the exception.
To this end, one possibility is to enclose the whole code, starting from the declaration of my_obj till the end of the program in a try block and catch the exception afterwards:
try {
A my_obj(arg1, arg2, arg3);
// ...
// about 100 other lines of code being executed if my_obj is created properly
}
catch (std::exception& e) {
// print a user-friendly error message and exit
}
But this looks to me a bit of an 'overkill'. Specifically since no other exceptions are thrown in the remaining 100 lines. Is there any other nicer way to accomplish this?
If the constructor throws, you don't have an object. std::optional<> is a type that means "We might not have an object here".
template <typename T, typename ... Args>
std::optional<T> try_make(Args&& ... args)
{ try {
return make_optional(std::forward(args...));
} catch (...) {
return {};
} }
Then
auto my_obj = try_make<A>(arg1,arg2,arg3);
if (my_obj) {
// about 100 other lines of code being executed if my_obj is created properly
}
One possibility would be the usage of a pointer (better use a smart pointer such as an unique_ptr as in below code). You would leave the unique_ptr empty, call the constructor in the try block and move the pointer into the unique_ptr. After that your other code executes. Surely you have to check for a valid pointer with the operator bool of unique_ptr in a simple if statement.
To simplify the usage of my_obj a reference is taken: A& my_obj_ref = *my_obj;.
std::unique_ptr<A> my_obj;
try {
my_obj = std::move(std::unique_ptr<A>(new A(arg1, arg2, arg3));
}
catch (std::exception& e) {
// print a user-friendly error message and exit
}
if (my_obj) { // needed if your exception handling doesn't break out of the function
A& my_obj_ref = *my_obj;
// ...
// about 100 other lines of code being executed if my_obj is created properly
}
Remember that this way would allocate your object on the heap instead of the stack.
You can abstract the object construction into a function that catches the exception:
template<typename... Args>
A make_a(Args&&... args) {
try {
return A(std::forward(args)...);
}
catch (std::exception& e) {
// print a user-friendly error message and exit
...
std::exit(EXIT_FAILURE);
}
}
// ... in the actual code:
A my_obj = make_a(arg1, arg2, arg3);
The above makes use of the fact that your program is exiting if construction fails. If the requirement were to continue running, the function could return std::optional<A> (or its boost equivalent if you don't have access to C++17.)
You have several options here, depending on how you want control to continue if the construction fails.
If you want to exit the function by throwing an exception, then you don't need to do anything, you can let the A construction exception propagate up.
If you want to exit by either throwing a different exception, or by performing some actions before letting the A construction exception propagate, then use a factory function (perhaps a lambda) that performs those actions, e.g.:
auto a_factory(T x, U y) -> A // or use perfect forwarding
{
try { return A(x, y); }
catch(...) {
log("constructing A failed...");
throw other_exception();
}
}
// ...
A my_obj = a_factory(x, y);
If you want to exit by returning a value, then you could still use the above method, but wrap the calling function in another function that catches expected exceptions and returns a value.
Or you could use the optional (below) or unique_ptr (as covered by other answers) technique, but executing a return statement from the catch block.
If you want to continue execution without a valid A, then you can do:
std::optional<A> opt_my_obj;
try
{
A temp(...args...);
opt_my_obj.swap(temp);
} catch(...)
{
// handling, you could return from the function here
}
// At this point you can test `if ( opt_my_obj )` to branch the flow.
// When you're at a point where you have verified the object exists, you
// can enable normal object syntax by writing:
A& my_obj = *opt_my_obj;
If you have several objects in your function that need this consideration, I would tend to suggest the version of having the whole function wrapped in a try...catch that can handle all the different exceptions.
I tend to do it simple: Throw the human readable message. This strategy works well when there is no choice, and usually, there isn't. There is a catch though, you want exception handling to be reasonably robust, so I package the message inside a std::array<char,4096> truncating if necessary and remembering the zero-terminator (I know that this could blow the stack but it should be fine if we are not in a recursive function), and throw that.
Example:
try
{
Options opts(argv);
SomeResource resource(opts.someParameter());
//...More actions that could throw
}
catch(const std::array<char,4096>& errmessage) //Or rather some other type that contains the message.
{
fprintf(stderr,"Error: %s\n",errmessage.data());
return -1; //Or any non-zero value
}
return 0;
Pros:
Quick to implement new constructors for new classes since there is one exception class only, that will works for everything
You will pick up any system messages right from the source
Cons:
Lack of context: The message will have to say something like "It was not possible to open the file foo: No such file or directory.". Without telling the user what the root cause for the exception. This problem is inherited from the exception model and cannot be solved without treating exceptions as glorified error codes
If you want to branch on exception content, you must parse the message, but I find this rarely needed. Possibly in the context of a compiler, but that would print that message anyway foo:54:1: Error: bar is not a baz.

C++ catching exception in constructor

How can I protect myself from using object which isn't fully created when using exceptions?
Should I catch in constructor ? Or maybe it's bad practice ? If I'll catch in constructor object will be created.
#include <stdio.h>
class A
{
public:
A()
{
try {
throw "Something bad happened...";
}
catch(const char* e) {
printf("Handled exception: %s\n", s);
}
// code continues here so our bad/broken object is created then?
}
~A()
{
printf("A:~A()");
}
void Method()
{ // do something
}
};
void main()
{
A object; // constructor will throw... and catch, code continues after catch so basically we've got
// broken object.
//And the question here:
//
//* is it possible to check if this object exists without catching it from main?
// &object still gives me an address of this broken object so it's created but how can I protect myself
// from using this broken object without writing try/catch and using error codes?
object.Method(); // something really bad. (aborting the program)
};
The language itself has no concept of an object being "invalid" in any detectable way.
If the exception indicates that a valid object can't be created, then it shouldn't be handled within the constructor; either rethrow it, or don't catch it in the first place. Then the program will leave the scope of the object being created, and it won't be possible to incorrectly access it.
If that isn't an option for some reason, then you'll need your own way to mark the object as "invalid"; perhaps set a boolean member variable at the end of the constructor to indicate success. This is flaky and error-prone, so don't do it unless you've got a very good reason.
If the object is in an invalid state when a certain exception is thrown, then I would let the exception unwind the call stack so the caller can be notified (and therefore react) to such things.
However, if the exception is one you can recover from, it may be worth trying to do so depend on your application. Make sure you use something like a logger or even simply stderr to indicate this is happening though.
I am going to suggest a first iteration of doing something more like this:
try {
throw "Something bad happened...";
}
catch(const std::exception e) {
cerr << e.what () << endl ; // Better off in the main
throw ;
}
Two things here:
Unless your exception handler handles the exception, it should throw.
Always use exception classes based upon std::exception to that you can always find out what the problem was as shown above.

Detecting when destructor running due to exception being thrown?

What is a good way in C++ to detect in a destructor that it is being run during unwind of the stack due to an exception being thrown as opposed to a normal exit of scope triggering the destructor? I'd like to know so that I can create a class that has some cleanup code that is always run on normal exit but skipped when an exception occurs.
std::uncaught_exception() (defined in <exception>) will tell you in your destructor if it was called because of an exception:
class A
{
public:
~A()
{
if (std::uncaught_exception()) {
// Called because of an exception
} else {
// No exception
}
}
};
Probably this article will help you. The article will show you the problems with std::uncaught_exception() and contains an advice how to deal with exceptions in destructors.
Don't do that unless you have a good reason. The stack unwinding is such a language feature that all automatic objects inside try block will be enforced to deallocate, so that the resources inside them have a chance to release.
You want skip cleanup in dtor during stack unwinding, which bypasses the original intention of it. And you'll run the risk of leaking resources.
Example
class CDBConnection
{
public:
CDBConnection()
{
m_db.open();
}
~CDBConnection()
{
if (!std::uncaught_exception())
m_db.close();
// if this is called during a stack unwinding,
// your DB connection will not be closed for sure.
// That's a resource leakage.
}
//..
private:
DB m_db;
};
void main()
{
//..
try
{
// code that may throw
CDBConnection db;
//..
}
catch(const CDBException& exp)
{
// properly handle the exception
}
}
Here is one way I can think of, but it seems clumsy:
{
myCleanupClass unwindAction;
try {
// do some work which may throw exception.
} catch (...) {
unwindAction.disableDestructorWork();
throw;
}
}

If a constructor throws exception, then does it make sense to have a global object of that class?

I am asking this question for general coding guidelines:
class A {
A() { ... throw 0; }
};
A obj; // <---global
int main()
{
}
If obj throws exception in above code then, it will eventually terminate the code before main() gets called. So my question is, what guideline I should take for such scenario ? Is it ok to declare global objects for such classes or not ? Should I always refrain myself from doing so, or is it a good tendency to catch the error in the beginning itself ?
If you NEED a global instance of an object whose constructor can throw, you could make the variable static, instead:
A * f(){
try {
//lock(mutex); -> as Praetorian points out
static A a;
//unlock(mutex);
return &a;
}
catch (...){
return NULL;
}
}
int main() {
A * a = f(); //f() can be called whenever you need to access the global
}
This would alleviate the problem caused by a premature exception.
EDIT: Of course, in this case the solution is 90% of the way to being a Singleton. Why not just fully turn it into one, by moving f() into A?
No, you should not declare such objects global - any exception will be unhandled and very hard to diagnose. The program will just crash which means that it will have very poor (below zero) user experience and will be rather hard to maintain.
As #Kerrek SB has mentioned in the comments, the answer to this is dependent on the reasons that can cause your class to throw. If you're trying to acquire a system resource that might be unavailable, I feel you shouldn't declare a global object. Your program will crash as soon as the user tries to run it; needless to say, that doesn't look very good. If it can throw a std::bad_alloc or some such exception that is unlikely under normal circumstances (assuming you're not trying to allocate a few GB of memory) you could make a global instance; however, I would still not do that.
Instead, you could declare a global pointer to the object, instantiate the object right at the beginning of main (before any threads have been spawned etc.) and point the pointer to this instance, then access it through the pointer. This gives your program a chance to handle exceptions, and maybe prompt the user to take some sort of remedial measures (like popping up a Retry button to try and reacquire the resource, for instance).
Declaring a global object is fine, but the design of your class is insignificant, it lacks details to be compatible with practical needs and use.
One solution no one seems to have mentionned is to use a function try
block. Basically, if the situation is that without the constructed
object, the rest of your program won't work or be able to do anything
useful, then the only real problem is that your user will get some sort
of incomprehensible error message if the constructor terminates with an
exception. So you wrap the constructor in a function try block, and
generate a comprehensible message, followed by an error return:
A::() try
: var1( initVar1 )
// ...
{
// Additional initialization code...
} catch ( std::exception const& ) {
std::cerr << "..." << std::endl;
exit(EXIT_FAILURE);
} catch (...) {
std::cerr << "Unknown error initializing A" << std::endl;
exit(EXIT_FAILURE);
}
This solution is really only appropriate, however, if all instances of
the object are declared statically, or if you can isolate a single
constructor for the static instances; for the non-static instances, it
is probably better to propagate the exception.
Like #J T have said, you can write like this:
struct S {
S() noexcept(false);
};
S &globalS() {
try {
static S s;
return s;
} catch (...) {
// Handle error, perhaps by logging it and gracefully terminating the application.
}
// Unreachable.
}
Such scenario is quite a problem, please read ERR58-CPP. Handle all exceptions thrown before main() begins executing for more detail.

what does "throw;" outside a catch block do?

I just stumbled this code:
void somefunction()
{
throw;
}
and I wonder: what does it mean?
The intent is probably that somefunction() is only ever called from inside some catch block. In that case, there would be an exception active when the throw; is executed, in which case the current exception is re-thrown, to be caught by the next outer handler that can handle that exception type.
If throw; is executed when an exception is not active, it calls terminate() (N4810, ยง[expr.throw]/4).
It re-throws the currently active exception. It would only make sense to call it (possibly indirectly) from a catch-block. This:
#include <iostream>
using namespace std;
void f() {
throw;
}
int main() {
try {
try {
throw "foo";
}
catch( ... ) {
f();
}
}
catch( const char * s ) {
cout << s << endl;
}
}
prints "foo".
For throw the concept of being "outside" or "inside" catch block is defined in run-time terms, not in compile-time terms as you seem to assume. So, if during run-time that throw is executed in run-time context of a catch block, then throw works as expected. Otherwise, terminate() is called.
In fact, if you take a closer look at how C++ exceptions are defined in the language specification, a lot of things about them are defined in run-time terms. Sometimes it even appears to be un-C++-like.
People have already explained what it means but it's potentially useful to know why you might see it. It's a useful way to construct a 'generic' exception handler that deals with exceptions based on their type so as to reduce the amount of duplicated code.
So, if we take Neil's example and expand on what f() might be doing we might end up with an implementation which does something like my LogKnownException() function that I proposed in this answer.
If you are working in an team that likes to log all manner of exceptions all over the place then rather than having a huge collection of catch blocks at all of these places (or even worse a macro) you can have a simple catch block that looks like this
catch(...)
{
LogKnownException();
}
Though I expect I'd change my previous example of LogKnownException() to one that simply allowed exceptions that it didn't want to log to propagate out and continue on in an unhandled fashion.
I'm not suggesting that this is necessarily a good thing to do, just pointing out that this is where you're likely to see the construct used.