Suppose I construct a RAII object, and that object may fail to construct. How do I handle this?
try {
std::vector<int> v(LOTS);
// try scope ends here because that's what the catch is for
} catch( const std::bad_alloc& ) {
// ...
}
// v? what v?
Granted, the default constructor of std::vector won't throw and that can help, but this is not the general case. A constructor may very well throw. If I want to handle any resource acquisition failure, how do I do that while still being able to proceed if it doesn't throw?
Edit: To clarify, my issue is that if a resource fails to acquire then I might want to try again, and so on. Maybe I can try acquiring an alternative resource.
Depends what you mean by "proceed". Whatever operation requires the resource will fail: that's what "requires" means. So when you want to continue after an error, you might end up writing code like this:
void something_using_RAII(thingummy &t) {
vector<int> v(t.size_required);
// do something using v
}
...
for each thingummy {
try {
something_using_RAII(this_thingummy);
} catch(const std::bad_alloc &) {
std::cerr << "can't manage that one, sorry\n";
}
}
That's why you should only catch exceptions when there's something worthwhile you can do with them (in this case, report failure and move on to the next thingummy).
If you want to try again on failure, but only if the constructor fails, not if anything else fails:
while(not bored of trying) {
bool constructor_failed = true;
try {
vector<int> v(LOTS);
constructor_failed = false;
// use v
} catch(...) {
if (!constructor_failed) throw;
}
}
This is more-or-less how std::new_handler works - the handler is called in the catch clause of a similar loop, although with no need for a flag.
If you want to try a different resource on failure:
try {
vector<int> v(LOTS);
// use v
} catch(...) try {
otherthing<int> w(LOTS);
// use w
} catch(...) {
// failed
}
If "use v" and "use w" are basically the same code, then refactor into a function and call it from both places. Your function is doing quite a lot at this point.
If an RAII constructor throws, all resources bound to RAII objects prior to the throwing point will be cleaned up properly. The C++ rules are sensibly designed to guarantee that.
If your v construction throws because of a bad_alloc then any RAII object created prior to v in the try block will be properly cleaned up.
So if you consequently use RAII, you don't need a manual try / catch like that, because the RAII objects handle cleanup for you. If you do need it for some reason, in the case above you could use swap like the following.
std::vector<int> v;
try {
std::vector<int> vtry(LOTS);
v.swap(vtry); // no-throw
} catch( const std::bad_alloc& ) {
// ...
}
// v!
If v can't be created, all the code that tries to use v can't be executed. Move the catch after the code that code uses v, in a place where it is reasonable to continue execution if there is no v.
All code that uses v needs to be in the try block. If the question is how to then narrow down the code which threw the exception, you can use some kind of flag to indicate where in the try block you are, like this:
string flag;
try
{
flag = "creating vector<int> v";
std::vector<int> v(LOTS);
flag = "performing blaggity bloop";
blaggity_bloop();
flag = "doing some other stuff";
some_other_stuff();
}
catch( const std::bad_alloc& )
{
cerr << "Bad allocation while " << flag << endl;
}
Related
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.
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.
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).
Is it OK to have the following code in my constructor to load an XML document into a member variable - throwing to caller if there are any problems:
MSXML2::IXMLDOMDocumentPtr m_docPtr; //member
Configuration()
{
try
{
HRESULT hr = m_docPtr.CreateInstance(__uuidof(MSXML2::DOMDocument40));
if ( SUCCEEDED(hr))
{
m_docPtr->loadXML(CreateXML());
}
else
{
throw MyException("Could not create instance of Dom");
}
}
catch(...)
{
LogError("Exception when loading xml");
throw;
}
}
Based on Scott Myers RAII implementations in More Effective C++ he cleanups if he alocates any resources i.e. pointers:
BookEntry::BookEntry(const string& name,
const string& address,
const string& imageFileName,
const string& audioClipFileName)
: theName(name), theAddress(address),
theImage(0), theAudioClip(0)
{
try { // this try block is new
if (imageFileName != "") {
theImage = new Image(imageFileName);
}
if (audioClipFileName != "") {
theAudioClip = new AudioClip(audioClipFileName);
}
}
catch (...) { // catch any exception
delete theImage; // perform necessary
delete theAudioClip; // cleanup actions
throw; // propagate the exception
}
}
I believe I am alright in just allowing exceptions to be thrown from CTOR as I am using a smart pointer(IXMLDOMDocumentPtr).
Let me know what you think....
C++ guarantees that in case of an exception all fully constructed objects will be destroyed.
Since m_docPtr is a member of class Configuration it will have been fully constructed before the class Configuration constructor body begins, so if you throw an exception from class Configuration body as you intended in your first snippet m_docPtr will be destroyed.
Do you plan to do anything in the catch block? If nothing, you probably do not need the try catch. On windows, I believe that catch(...) catches hardware interrupts (experts please correct), something to keep in mind.
It's important to detect an error when you close a file to which you were writing, because the last part of your data could be flushed during the close, and if it's lost then your last write effectively failed and someone should know about it. The destructor for a file object is a nice place to automatically close it, but people say not to throw exceptions from destructors, so if the close fails then how do you know about it?
I've heard people recommend calling the close() method of the file manually. That's sounds nice, except what happens if the close() methods of multiple files all fail in a situation like this:
MyFile x(0), y(1), z(2);
x.close();
y.close();
z.close();
?
Well, it seems that if the close() method of 'x' throws an exception then you've done well to uphold the rule to avoid throwing exceptions in the destructor of 'x', except now you're good-intentioned early calls to the close() methods of 'y' and 'z' won't execute until their destructors. So, then when the close() method of 'y' is called in the destructor of 'y' or the close() method of 'z' is called in the destructor of 'z', and if they do throw exceptions then you're screwed.
Is there a reasonable way to not be screwed in such a situation?
Yes, catch the exception thrown from close in the destructor.
It is vitally important that a C++ destructor not throw an exception period. To do otherwise will mess up many of the resource management routines within virtually every available library.
True, you lose the failure information in this case by catching the exception. If the user is actually concerned about the error, they can manually call close and deal with the exception.
This is a FAQ item: 17.3 How can I handle a destructor that fails?
Edit:
Well, it seems that if the close()
method of 'x' throws an exception then
you've done well to uphold the rule to
avoid throwing exceptions in the
destructor of 'x', except now you're
good-intentioned early calls to the
close() methods of 'y' and 'z' won't
execute until their destructors.
No. Dtors for y and z will be called when the stack unwinds provided you have a try-catch block installed around the MyFile ... z.close() part. A better idea would be to put a close in the dtor as well. The dtor for x will not be -- so some cleanup is in order in the catch block.
I suggest you run the following program to better understand dtor-calls in the case of an exception (once as-is and again by uncommenting the S x line):
#include <iostream>
using namespace std;
struct s {
s(int i = 0) : m_i( i ) { cout << __func__ << endl; }
~s() { if (m_i == 0) except(); cout << __func__ << endl; }
void except() { throw 42; }
int m_i;
};
int main() {
try
{
s y(2), z(3);
/* s x */
y.except();
}
catch (...) { cout << "exception\n"; }
cout << "stack unwound\n";
}
You shouldn't throw from a destructor -- so:
If close had calls that threw exceptions, I would swallow them and do one of the following:
Option 1: Write out an error message and kill the program.
Option 2: Make the error available via a wrapper object (I would probably do this) or a global variable or (prefferably) a variable that is in thread local memory.
Option 1 and 2 both seem reasonable here.
With option 2 and the wrapper you would do:
WrapFileX.close();
WrapFileY.close();
WrapFileZ.close();
if(WrapFileX.hasError || WrapFileY.hasError || WrapfileZ.hasError)
{ //log
exit(1)
}
In this example, I don't see why anything should be thrown. I don't think that this scenario is exception-worthy at all. In theory, the close didn't fail, it just failed to write the rest of the buffer; which isn't a very exceptional situation. It can be handled and should be handled, unless there's a reason that the file needs to be closed right this instant.
I, personally, would just have my close() function block until the writes have completed, then continue with closing.
The rule as I see it is:
If you don't care about the exception then let the destructor do the close work (and catch and discard the exceptions). If you do care (AND can do something about it) then close manually and catch the exception and do the appropriate work.
{
std::fstream X("Plop_X");
std::fstream Y("Plop_Y");
std::fstream Z("Plop_Z");
// Do work
try
{
X.close();
}
catch(Plop const& e)
{
// Fix the exception
// Then make sure X closes correctly.
// If we can't fix the problem
// rethrow
if (badJuJu)
{ throw;
}
}
// Don't care about Y/Z let the destructor close them and discard the exception.
}
try {
x.close();
y.close();
z.close();
}
catch {
//do what ever you need to do here, then close() what' you'll need to close here
}
That's what i would do ,the point is maybe you don't know which one throw the exceptions, and which one left for closing.
First, MyFile's destructor should catch the exception (and that's an incredibly strong "should" - it's not "must" because the behaviour if it doesn't is well-defined, but it's almost never desirable):
~MyFile() {
try {
close();
} catch(...) {}
// other cleanup
}
Next, callers should decide whether they want to handle the error. If they don't, then they can just let the destructor be called. If they do, then they have to call close themselves. If your example of three files, supposing that once one of them has failed you don't care about the others, you can do this:
MyFile x(0), y(1), z(2);
try {
x.close();
y.close();
z.close();
} catch(...) {
std::cerr << "something failed to close\n";
}
If you want to know exactly which failed, you need to ensure that all three close functions are actually called:
MyFile x(0), y(1), z(2);
try {
x.close();
} catch(...) {
std::cerr << "x failed to close\n";
}
try {
y.close();
} catch(...) {
std::cerr << "y failed to close\n";
}
try {
z.close();
} catch(...) {
std::cerr << "z failed to close\n";
}
Of course you might want to common up that code a bit. Also, if you know everything close can throw, then you could have a better catch clause than (...).
This is possibly why the close() function of streams in the standard library doesn't throw an exception unless that behaviour has been enabled by the user setting the exception mask.