I was writing code with exception handling the other day, and I had a few questions about exceptions, their guarantees and throwables.
Basically, say you have:
class X {
string m_str;
X() : m_str("foo")//what if this throws?
{
ifstream b("a.in")//what if this throws?
}
And after running through all the articles I could find, I still have no idea what is the clean way to handle this.
Say I have a code like:
{
...
X myInstanceOfClassX;
...
}
Should I wrap the code in catch(exception &)? And if I do that, does string and ifstream guarantee a strong guarantee, that no resources are leaked and nothing has been left half opened?
Also, if my class throws myexception, that is derived from exception, catch(exception &) seems to let it through. So that leaves me with catch(...) which IIRC catches access violation?.? Is there another way?
Then there was a piece of information somewhere that any exception thrown in subconstructors of object constructor shouldn’t be caught, and constructor should throw in case any of the member objects throw.
And what if the code above would have been called not from constructor, but from regular a function void foo(), which exceptions should I catch? outofmemory_something, filenotfound_something? Where can I find the definitions of what STL objects can throw? Are they implementation specific?
Where is the authoritative source where I could clear all my doubts and questions on this topic?
So far, it seems that handling exceptions is like dancing in a big pile of gooo. Error codes seem A LOT simpler and safer…
If either of these throw
Then the object you were creating will not exist.
If an exception is thrown in the constructor of an object, then all fully created members are destructed (using the their destructor) and memory for the object is returned to the system. Thus any members that are not fully constructed at the throw point will not be destroyed (as they have not been created).
Even if you catch an exception (outside the object) there is no object to work on as it never existed (the object only starts its lifespan after the constructor completes).
In the above you are guaranteed there are no leaks or open resources.
If your exception is derived from std::exception then
catch(std::exception&)will work. If it is not working then you are doing something wrong (but we need more detail (like the code that throws and the code that catches, an English description is not adequate)).Probably the best option and as a general rule not bad advice.
You should only catch exceptions if you can do something about it. Usually this is nothing so don;t catch them let the application quit normally (via the exception unwinding the stack).
You’re question are so varied that that is hard.
I could recommend "Exceptional C++" by Herb Sutter.
You are wrong there. Exceptions are much easier. You just seem to be over-thinking it and getting confused. That is not to say that error codes do not have their place.
If something goes wrong
and you can not fix it locallythen throw an exception. All the classes in the standard are designed with exception in mind and will behave correctly. So that just leaves your classes.Rules of thumb: (for your objects)
Note: You can have multiple things like std::string or std::ifstream as they are the ones controlling the resource (they each control one resource so your class is not controlling the resource). A resource (in this context) is something that you must manually create/destroy.
That’s it, the rest auto-magically works.