Should my exception classes provide details in public fields in addition to what()?
Consider for example boost::property_tree::ptree_bad_path which might give a message:
"No such node (mynode.value1)"
The only way to access the path ("mynode.value1") is by parsing the string. Is there an argument against adding additional public fields to carry such information, that is:
class ptree_bad_path : public ptree_error {
public:
const std::string path; // <- additional detail by public field
....
Are there drawbacks to this approach?
In theory, you run the risk of having your program terminate if you ever have two unhandled exceptions at the same time. This is, however, a rather rare situation.
Throwing during the preparation of the exception: fine (though you won't get the exception you expected)
Throwing during the copy of the exception (often elided, avoidable): crash
Throwing during the unwinding: crash
Throwing during the handling of the exception (catch): fine (after all, rethrowing a different exception is common)
So, the avoidable risk here is if the copy constructor of your exception might happen to throw. It is trivial to elude the issue by moving the state off to a shared_ptr contained within the exception. It makes copies a bit "special" (since they share their state with the original) but if it's documented properly it should not cause any grief.
The greater risk is during stack unwinding. It only occurs if a destructor throws, though.
Personally, the exceptions I use contain:
an error code (for the API to display/encode properly, all error messages are mapped to a code, it helps in Chinese/Korean/Japanese, really)
a log message, with some details (ID/name of the item that cause the issue, original error when translating another exception, whatever helps!)
the function/file/line at which the exception was thrown
the time at which the exception thrown
additional notes (appended "on the fly" during stack unwinding)
a complete backtrace (using Linux specific functions)
The only controversial point here is the on the fly bit, since it might effectively crash. On the other hand, I work on servers so crashes are easily (and urgently) fixed and for the last 5 years I was careful enough not to cause a crash (this way ;)).
Note that this scheme is obviously only available if you use exceptions sparsely. If you routinely throw a dozen exceptions per task, the performance might be unnacceptable. On the other hand, the Zero Cost model used by major compilers already harshly penalize the exceptional path so...
Your exception class should contain all the information required to handle the error. This usually means tagging it with what went wrong and any context necessary. It is a good idea to store the path in your exception class.
Are there drawbacks to this approach?
Try to avoid having the members themselves throw as they will call std::terminate.
This is just my opinion, but if you're going to throw an exception you might want to make sure it has enough information for you to know (a) what caused the exception, and (b) where the exception was thrown.
You are probably (hopefully) not going to show the exception to the end user, so therefore logging the exception becomes something that purely enables/improves supportability. So from a development perspective, you basically want to be in a position where you know as much as possible about what happened.
Of course you're right in that you are walking a fine wire here. You don't want to have such complex code in your exception handling that it runs the risk of throwing its own exception!
Your exceptions may carry as much information as their catchers are ready (and willing) to use. If your particular application can use this additional information, you can write your own exception classes with peace of mind. In any case, all exception classes should inherit from std::exception to ensure that catch clauses not expecting custom exceptions will work correctly.
A different issue is exposing those classes on a library to be used by third party clients. In this case you should consider carefully whether the benefits of this additional information outweight the hassle introduced by the additional interface and even the possibility that it may not be used at all.
EDIT: As Pubby says, your exception classes should never throw to avoid unwelcome calls to std::terminate(). In general, no exception-related code should ever throw, and this includes destructors for any class.
Related
I recently learned that in C++ there is a single "slot" for an active exception and this raise some questions for me.
The example that I know is something like:
void f()
{
MyClass c;
throw MyException;
}
When we get to the throw the function immediately returns and then the exception starts looking for its matching catch. But let's say that during the return of f, when the destructor of c is called, suppose it throws another exception of type MyException2, in this case from what I understood the program always crashes because there is only one "slot" for an active exception so when MyException2 occurs there is a problem.
I would like to know if there is a reason for this specific approach since most other languages have some sort of stack and give a message like During handling of this exception this other exception occurred, with clear stack traces for both exceptions.
Is there a reason for this problem not being approached? Things like a stack of active exceptions and if MyException2 occurs while MyException1 is active then it will just resolve and then return to the handling of MyException1?
I'm sorry if I may not be familiar with the proper terms, this is a purely education question from someone who wishes to know more about the "guts" of the language out of pure fascination.
What you’re thinking about in, say, Python looks like
try: risky()
except Error as e:
some_cleanup(e)
also_risky() # raises OtherError
if still_unhappy(): raise
more_handling()
The corresponding code in C++ behaves the same way and does not automatically terminate:
try {risky();}
catch(const Error &e) {
some_cleanup(e);
also_risky(); // throws OtherError
if(still_unhappy()) throw;
more_handling();
}
The reason is that the original exception might or might not have been handled successfully (is more_handling necessary, or is it just part of retrying?). C++ makes the optimistic statement that it was, whereas by default Python 3 makes the pessimistic statement that the new exception is fallout from the old. C++ could of course provide a syntax to indicate the other choice, like Python does (raise new from None), but such an “associated exception” would be more difficult still to deal with in a static-typing context than exceptions already are, and one of the main motivations is absent since C++ expects the program to provide whatever backtrace-reporting mechanisms are desired.
The parallel is stronger if you consider destructors in both languages (especially in CPython where many of them are reliably invoked during stack unwinding): here, Python simply prints to standard error if a destructor throws, because to do otherwise would greatly complicate its internal resource management. C++ is actually more permissive in that a destructor can throw so long as it was not invoked directly by the unwinding mechanism; this is dangerous, but is occasionally used by experts to good effect. On the other hand, C++ most certainly does not consider writing to standard error a sufficient option for handling an exception, so if its resource management encounters such a problem, it’s all over.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I am working on a project where we are restructuring old C code into new C++ where for error handling we are using exceptions.
We are creating different exception types for different modules.
I don't see it is worth but I don't have any valid argument to prove my point. So if we would have written the standard library, you would get to see vector_exception, list_exception and so on.
While thinking about it I stumbled upon this question:
When should you create your own exception type and when should you stick to the exceptions already created in std library?
Also, what could be the problems that we may face in the near future if we go by the above approach?
Create your own exception types when:
you might want to differentiate them when handling. If they're different types, you have the option to write different catch clauses. They should still have a common base so you can have common handling when that is appropriate
you want to add some specific structured data you can actually use in the handler
Having separate list and vector exceptions doesn't seem worthwhile, unless there's something distinctively list-like or vectorish about them. Are you really going to have different catch handling depending on which type of container had an error?
Conversely it could make sense to have separate exception types for things that might be recoverable at runtime, versus things that are rolled-back but could be retried, versus things that are definitely fatal or indicate a bug.
Using the same exception everywhere is easy. Especially when trying to catch that exception. Unfortunately, it opens the door for Pokemon exception handling. It brings the risk of catching exceptions you don't expect.
Using a dedicated exception for all the different modules adds several advantages:
A custom message for each case, making it more useful for reporting
Catch can capture only the intended exceptions, more easily crashes on unexpected cases (yes, thats an advantage over incorrect handling)
On crash, IDE can show the exception type, helping even more with debugging
I think that in addition to the reasons in other answers could be code readability, because a lot of time programmers spend supporting it. Consider two pieces of code (assuming they throw "empty frame" error):
void MyClass::function() noexcept(false) {
// ...
if (errorCondition) {
throw std::exception("Error: empty frame");
}
}
void MyClass::function() noexcept(false) {
// ...
if (errorCondition) {
throw EmptyFrame();
}
}
In the second case I think it is more readable, and the message for the user (which printed with what() function) is hidden inside this custom exception class.
I see two possible reasons.
1) If you want to store in the exception class some custom information about the exception, then you need an exception with extra data members. Often you will inherit from one of the std exception classes.
2) If you want to differentiate between exceptions. For instance suppose you have two distinct invalid argument situations and in your catch block you want to be able to differeentiate between the two. You can create two child classes of std::invalid_argument
The issue I see with each element of the STL firing a distinct memory exception is that some parts of the stl are built on others, so queue would have to catch and translate list exceptions, or clients of queue would have to know to handle list exceptions.
I can see some logic in separating the exceptions from different modules, but I can also see the logic of having a project-wide exception base class. I can also see the logic of having exception type classes.
The unholy alliance would be to build an exception hierarchy:
std::exception
EXProjectBase
EXModuleBase
EXModule1
EXModule2
EXClassBase
EXClassMemory
EXClassBadArg
EXClassDisconnect
EXClassTooSoon
EXClassTooLate
Then insist that every actual fired exception is derived from BOTH a module and a classification. Then, you can catch whatever makes sense to the catcher, such as a disconnection, rather than Having to separately catch HighLevelDisconnect and LowLevelDisconnect.
On the other hand it is also completely fair to suggest that the HighLevel interface should have completely dealt with LowLevel failures, and they should never be seen by the HighLevel API client. This is where catching by module would be a useful last-ditch feature.
I would ask, of the try...catch section, "does this code know how to recover from the error, or not?
Code which uses try...catch is anticipating that an exception could happen. Reasons that you would write try...catch at all instead of letting the exception simply pass through are:
Add some code to make the parent function exception safe. A lot of this should be done quietly with RAII in destructors, but sometimes (e.g. a move operation) need more work to roll-back a partially completed job, it depends on the level of exception safety you want.
Emit or add some debugging information and rethrow the exception.
Try to recover from the error.
For cases 1 and 2 you probably don't need to worry about user exception types, they will look like this
try {
....
} catch (const std::exception & e) {
// print or tidy up or whatever
throw;
} catch (...) {
// print or tidy up or whatever
// also complain that std::exception should have been thrown
throw;
}
This will probably by 99% of real world cases, in my experience.
Sometimes you will want to recover from the error. Maybe the parent function knows that a library will fail in certain conditions which can be fixed dynamically, or there is a strategy for re-attempting a job using different mechanisms.
Sometimes the catch block will be written specifically because the lower-level code has been designed to throw exceptions as part of its normal flow. (I often do this when reading untrusted external data, where many things can predictably go wrong.)
In these, rarer cases, user-defined types make sense.
In our application, we log any crashes into a log file with stack trace included. We can use these reports to identify crash causes.
The problem is, that we tend to catch std::exception on several places (a lot actually), which makes the report effectively useless when bad_alloc is thrown, as the stack trace is lost.
How to change the behaviour, so instead of throwing bad_alloc, the program aborts? As we write in 3 different operating systems, so 3 different std implementations are used, changing the std itself is something we would like to avoid.
Besides a rethink or redesign to catch more tailored exceptions (which I really recommend) you have two solutions:
Use the "no-throw" variants of operator new and operator new[]. Check for a returned null pointer, and abort.
Set a new handler that calls std::terminate.
I checked the exception hierarchy (http://en.cppreference.com/w/cpp/error/exception) and it seems, that we never need to catch anything outside std::runtime_exception and all of our internal exception types are derived from std::runtime_exception.
So I just changed that the broadest catch we have in our program is std::runtime_error so std::bad_alloc is becomes exception, which we can properly manage.
Edit: This can only be used since C++11
How to handle failed methods:
using exceptions
making the methods return bool
The first approach is when something goes wrong to throw an exception.
But the problematic code needs to be placed in a try block,
and then you need to write the catch block.
The second approach you need to check the return value from
the method, and then do something.
So basically isn't it the same mechanism? You have two parts:
detecting that something goes wrong and then doing something about it.
So does it matter then which approach I use?
The main benefit with exceptions is that they are non-local. You can catch an exception several invocation layers away from where it was thrown. That way, code in between doesn't have to care about exceptions (except ensuring proper cleanup during unwinding, i.e. being exception safe), which makes it less likely that an exceptional situation gets forgotten. But this benefit comes at a price: stack unwinding is more complicated than simply returning a value. In terms of performance, the return value approach is usually simpler.
So I'd use these to choose: if for some reason the only reasonable place to deal with a problem is directly at the location where the function was called, and if you are fairly certain that every caller will include some kind of error handling code in any case, and is not likely to forget doing so, then a return value would be best. Otherwise, I'd go for an exception.
Basically you can reach the same behavior with both approaches, but Exception can give 2 added values:
1) You don't have to handle the error in the exact calling method, it can be anywhere up the call stack. this remove the if(!doSomthing()) return false; from the code when you just want to pass the error up.
2) It allow you to write a block of code, under one try and handle all the errors under it in one catch block.
There is no simple answer. For instance, here is the conclusion of the article C++ Exceptions: Pros and Cons
There is no simple answer to the "exceptions or error codes" question. The decision needs to be made based on a specific situation that a development team faces. Some rough guidelines may be:
If you have a good development process and code standards that are actually being followed, if you are writing modern-style C++ code that relies on RAII to clean up resources for you, if your code base is modular, using exceptions may be a good idea.
If you are working with code that was not written with exception safety in mind, if you feel there is a lack of discipline in your development team, or if you are developing hard real-time systems, you should probably not use exceptions.
My personal rule is to raise exception only when something exceptional occurs, ie when the problem may not have appeared at all. Otherwise I use return value (most of the time).
For example, when searching for a file that MUST exists, not finding it raises an exception. But if the file may or may not exists, not finding it is not exceptional so no need for an exception.
There's no answer for all situations. Both approaches have strengths and weaknesses:
Exceptions:
are slightly more verbose to handle locally
can simply be ignored if the error can't be handled locally
can carry as much information as you like about the error, both statically (in the exception type) and dynamically (in the thrown object)
require a handler somewhere to avoid terminating the program
may have more runtime overhead (but may have less when nothing is thrown, depending on how they're implemented)
require the code to be exception safe
Return values:
must be manually passed up the stack if not handled locally: prone to bugs if you forget
have a fixed type, limiting how much information they can carry (although you could return a pointer to a polymorphic type, and deal with the associated lifetime management issues)
are awkward to use if the function also needs to return something on success
There are two main differences: (a) it is easier for the calling code to just silently ignore the boolean status code. (b) Exceptions provide more context than mere false. You can distinguish business-logic errors from I/O errors from input validation errors etc.
I prefer bools. I'd say its personal preference.
I have found it easier to read.
Is it possible to make a destructor catch exceptions and then re-throw them?
If so, how would I do that, since there isn't a clear place for a try statement?
Basically, I want to ideally do:
CMyObject::~CMyObject()
{
catch(...) // Catch without a try. Possible?
{
LogSomeInfo();
throw; // re-throw the same exception
}
// Normal Destructor operations
}
Background
I have a large, complex application that is throwing an unhandled exception somewhere.
I don't have easy access to main or the top level message-pump or anything similar, so there's no easy place to catch all unhandled exceptions.
I figure any unhandled exception has to pass through a bunch of destructors as the stack is unwound. So, I'm contemplating scattering a bunch of catch statements in destructors. Then at least I'd know what objects are in play when the exception is thrown. But I have no idea if this is possible, or advisable.
EDIT: You can use std::uncaught_exception to check if an exception is currently being thrown (i.e. if stack unwinding is in progress due to an exception). It is not possible to catch that exception or otherwise get access to it from your destructor. So if your logging doesn't need access to the exception itself, you can use
CMyObject::~CMyObject()
{
if(std::uncaught_exception()) {
LogSomeInfo(); // No access to exception.
}
// Normal Destructor operations
}
Note that this question was asked in 2013, meanwhile std::uncaught_exception was replaced with std::uncaught_exceptions (notice the additional s at the end) which returns an int. For a rationale, see http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4152.pdf, so if you are using C++17, you should prefer the new version. The above paper also explains why the old std::uncaught_exception will not work as expected in some situations.
Another option might be std::set_terminate. This is useful if you want to have a method called when an exception is not caught and about to terminate the program. In the terminate handler, I usually print some information about the exception and a (demangled) backtrace of where it originates from to my log file before finally terminating the program. This is compiler and system specific, but a real helper as it saves a lot of time if you write server processes and often the log file is all you get from ops.
You can use std::uncaught_exception() which returns true if and only if there is an exception being processed. It has been available since C++98, and is superseded by std::current_exception which returns a std::exception_ptr.
However you must be careful not to throw another exception in an unguarded context, otherwise std::terminate will be caught. Example:
X::~X() {
if (std::uncaught_exception()) {
try {
LogSomeInfo();
// and do something else...
} catch(...) {}
}
}
A destructor cannot catch the exception that is causing the destruction of the instance.
You can only know if there is any "active exception" (see uncaught_exception) during the destruction (or, in C++17, how many of them there are there with uncaught_exceptions) but it's possible that the exception(s) are indeed going to be handled after that.
Dealing with exceptions is very hard, much harder than someone may think at a first sight and the reason is that exception safety doesn't scale by composition. This in my opinion means that is basically impossible to have non trivial stateful subsystems with strong exception safety (in case of an exception being thrown nothing happened to the internal state). This was discovered long ago (see 1994 Tom Cargill's "Exception handling: A False Sense of Security") but apparently is still ignored by large part of the C++ community.
The only reasonable way to handle exceptions I can think to is to have subsystems with clear well defined interfaces with thick "walls" (no side effect happening inside may escape), and that can be re-initialized to a well known state from scratch if needed when something goes wrong. This not trivial but can be done correctly to a reasonable extent.
In all other cases the global state of the system when an exception is caught is indefinite at best at the point of catch and there are in my opinion few use cases in which you can do anything in such a condition except dying immediately as loudly as possible instead of taking further actions without indeed knowing what is going on (dead programs tell no lie). Even keeping on calling destructors is somewhat questionable in my opinion.
Or you may try to be as functional as possible, but that's not an easy path either (at least for my brain) and it's also moving far away from reality (most computers are mutable objects with many billions of bits of mutable state: you can pretend this is not the case and they're instead mathematical functions with no state and with predictable output dependent on input... but in my opinion you're just deluding yourself).