In C++, RAII is often advocated as a superior approach to exception handling: if an exception is thrown, the stack is unwound, all the destructors are called and resources are cleaned up.
However, this presents a problem with error reporting. Say a very generic function fails, the stack is unwound to the top level and all I see in the logs would be:
Couldn't read from socket: connection reset by peer.
...or any equally generic message. This doesn't say much about the context from which the exception is thrown. Especially if I'm running something like an event queue processing loop.
Of course I could wrap every call to socket reads with a try/catch block, catch the exception, construct a new one with more detailed context information and re-throw it, but it defeats the purpose of having RAII, and is slowly but surely becoming worse than handling return error codes.
What's a better way for detailed for error reporting in standard C++? I'm also open to suggestions involving Boost.
As James McNellis suggested here, there is a really neat trick involving a guard object and the std::uncaught_exception facility.
The idea is to write code like this:
void function(int a, int b)
{
STACK_TRACE("function") << "a: " << a << ", b: " << b;
// do anything
}
And have the message logged only in case an exception is actually thrown.
The class is very simple:
class StackTrace: boost::noncopyable // doesn't make sense to copy it
{
public:
StackTrace(): mStream() {}
~StackTrace()
{
if (std::uncaught_exception())
{
std::cout << mStream.str() << '\n';
}
}
std::ostream& set(char const* function, char const* file, unsigned int line)
{
return mStream << file << "#" << line << " - " << function << " - ";
}
private:
std::ostringstream mStream;
};
#define STACK_TRACE(func) \
StackTrace ReallyUnwieldyName; \
ReallyUnwieldyName.set(func, __FILE__, __LINE__)
One can use __PRETTY_FUNC__ or equivalent to avoid naming the function, but I have found in practice that it was too mangled / verbose for my own taste.
Note that you need a named object if you wish it to live till the end of the scope, which is the purpose here. We could think of tricky ways to generate a unique identifier, but I have never needed it, even when protecting narrower scope within a function, the rules of name hiding play in our favor.
If you combine this with an ExceptionManager (something where exceptions thrown register themselves), then you can get a reference to the latest exception and in case of logging you can rather decide to setup your stack within the exception itself. So that it's printed by what and ignored if the exception is discarded.
This is a matter of taste.
Note that in the presence of ExceptionManager you must remain aware that not all exceptions can be retrieved with it --> only the ones you have crafted yourself. As such you still need a measure of protection against std::out_of_range and 3rd party exceptions.
Say a very generic function fails, the stack is unwound to the top level and all I see in the logs would be [...]
What's a better way for detailed for error reporting in standard C++?
Error handling isn't local to a class or library - it is a application level concern.
Best I can answer you question is that the error reporting should be always implemented by looking first and foremost at the error handling. (And the error handling also including the handling of the error by the user.) Error handling is the decision making about what has to be done about the error.
That is one of the reasons why error reporting is an application level concern and strongly depends on the application workflow. In one application the "connection reset by peer" is a fatal error - in another it is a norm of life, error should be silently handled, connection should be reestablished and pending operation retried.
Thus the approach you mention - catch the exception, construct a new one with more detailed context information and re-throw it - is a valid one too: it is up to the top level application logic (or even user configuration) to decide whether the error is really an error or some special (re)action has to taken upon the condition.
What you have encountered is one of the weaknesses of so called out-of-line error handling (aka exceptions). And I'm not aware of any way to do it better. Exceptions create a secondary code path in the application and if error reporting is vital the design of the secondary code path has to treated just like the main code path.
Obvious alternative to the out-of-line error handling is the in-line error handling - good ol' return codes and log messages on the error conditions. That allows for a trick where application saves all low-severity log messages into internal (circular) buffer (of fixed or configurable size) and dumps them into the log only if high-severity error happens. This way more context information is available and different layers of application do not have to be actively aware of each other. That is also standard (and sometimes literally "standard" - mandated by law) way of error reporting in application fields like safety and mission critical software, were one is not allowed to miss errors.
I've never actually done this, but you could roll your own "stacktrace":
struct ErrorMessage {
const char *s;
ErrorMessage(const char *s) : msg(s) {}
~ErrorMessage() { if (s) std::cout << s << "\n"; }
void done() { s = 0; }
};
void someOperation() {
ErrorMessage msg("Doing the first bit");
// do various stuff that could throw
msg = "Doing the second bit";
// do more stuff that could throw
msg.done();
}
You can have several levels of this (although not necessarily use it at every level):
void handleFoo() {
ErrorMessage msg("Handling foo event");
someOperation();
msg.done();
}
And add more constructors and members:
void handleBar(const BarEvent &b) {
ErrorMessage msg(std::stringstream("Handling bar event ") << b.id);
someOperation();
msg.done();
}
And you needn't write the messages to std::cout. It could be to some logging object, and the object could queue them, and not actually output them to the log unless the catch site tells it to. That way, if you catch an exception that doesn't warrant logging, nothing is written.
It's not pretty, but it's prettier than try/catch/throw or checking return values. And if you forget to call done on success (for example if your function has multiple returns and you miss one), then you will at least see your mistake in the logs, unlike a resource leak.
[Edit: oh, and with a suitable macro you can store __FILE__ and __LINE__ in the ErrorMessage.]
You could add a call stack to your exception. I'm not sure how good this works for release builds but works like a charm with debug. You could do this in the constructor of your exception (to encapsulate it). See here for a starting point. This is possible as well on Linux - eventhough I dont remember how exactly.
I use RAII and exceptions and just have various unit-test-like assert statements throughout the code - if they fail, the the stack unwinds to where I can catch and handle them.
#define APP_ASSERT_MSG(Class,Assertion,szDescription) \
if ( !(Assertion) ) \
{ \
throw Class(__LINE__,__FILE__,szDescription); \
}
For most of my particular use case, all I care about is logging debug information, so my exception has the file and line number in it along with an error message (message is optional as I have an assert without it as well). You could easily add FUNCTION or an error code of some type for better handling.
I can then use it like this:
int nRet = download_file(...);
APP_ASSERT_MSG(DownloadException == ERR_OK, "Download failed");
This makes error handling and reporting much easier.
For really nasty debugging, I used GCC's function instrumentation to keep a trace list of what's going on. It works well, but slows down the app quite a bit.
What I do regularly, FWIW, is not use exceptions, but rather explicit error handling in a standard format (ie: using a macro). For example:
result = DoSomething();
CHECK_RESULT_AND_RETURN_ON_ERROR( result );
Now, obviously, this has many limitations design-wise:
Your return codes may need to be somewhat uniform
Code is cluttered with macros
You may need many macros for various check conditions
The upside, though, is as Dummy00001 said: you can effectively generate a stack trace on demand in the event of a serious error, by simply caching the results. I also use this paradigm to log all unexpected error conditions, so I can adjust the code later to handle unexpected conditions which occur "in the wild".
That's my 2c.
Here's how I handle error reporting in my libraries (this may or may not suit your situation).
First, as part of your design you want a "core" or "system" library that all this common logic will sit in. All you other libraries will then link to the core and use its error reporting APIs, so your whole system has a single compact chunk of logic for handling this mess.
Inside the core, provide a set of logging MACROS such as "LogWarning" and "LogFatal" with documented behavior and expected usage- for example, LogFatal should trigger a hard abort of the process but anything lower than "LogError" is simply advisory (does nothing). The macros can provide a "printf" interface that automatically appends the "LINE", "FILE", and "FUNC" macros as arguments to the underlying singleton object that handles your error reporting.
For the object itself I'll defer to you. However, you want public APIs that configure your "drains"- e.g. log to stderr, log to logfile, log to MS Services log, etc. You also want the underlying singleton to be thread safe, re-entrant where possible, and very robust.
With this system, you can make "exception reporting" ONE MORE DRAIN TYPE. Just add an internal API to that error manager object that packages your logged message as an exception, then throws it. Users can then enable AND DISABLE exceptions-on-error behavior in your code with ONE LINE in their apps. You can put try-catches around 3rd party or system code in you libraries that then calls a "Log..." macro in the catch clauses to enable clean re-throw behavior (with certain platforms and compiler options you can even catch things like segfaults using this).
Related
I was reading this document Error Handling on the boost website.
in the point five i found this suggestion.
Blockquote
"Don't worry too much about the what() message. It's nice to have a message that a programmer stands a chance of figuring out, but you're very unlikely to be able to compose a relevant and user-comprehensible error message at the point an exception is thrown. Certainly, internationalization is beyond the scope of the exception class author. Peter Dimov makes an excellent argument that the proper use of a what() string is to serve as a key into a table of error message formatters. Now if only we could get standardized what() strings for exceptions thrown by the standard library..."
I'm wondering on how this can be realized( in a language independent way ) but i'm not so experienced.. can you make some examples ?
Thanks!
As it happens so often, "it depends" :-)
I find the what() method extremely useful in command-line applications written for advanced users (I develop scientific software). Here internationalization is not an issue as everyone understands English, and in most cases it is indeed possible to provide error messages that are meaningful to the users.
Another approach I often use is an "error class". An instance of such a class "collects" error messages and warnings while the main application runs and it prints what has been collected only upon exit. It looks like this (only the skeleton is shown to illustrate the principle):
class Errors {
public:
void add_error(const std::string& errmsg);
void add_warning(const std::string& warnmsg);
// print all errors and warnings
void print(std::ostream& out) const;
// no errors, no warnings
bool perfect() const { return (_errs.size() + _warns.size()) == 0; }
// no errors, maybe some warnings
bool ok() const { return _errs.size() == 0; }
// ...
private:
std::vector<std::string> _errs, _warns;
};
The output of what() can be saved directly in an Errors object:
try {
// ...
} catch (const std::exception& ex) {
errors.add_error(ex.what());
// ...
}
or you can generate very nice error messages, possibly internationalized, in the catch block as you see fit by translating the output of what() or by using complex exception objects that encapsulate the necessary information. Then at the end of the program you can give the user a complete list of what went wrong by invoking the print() method.
Finally, if you write software for "non-expert users", then all the caveats noted by others above apply. Basically, internationalized, easy-to-understand error messages should be presented, and only as few as possible. You should "hide" the exceptions, so to speak. No one likes popups saying "Error #x7582764 occurred, exiting" :-)
The issues of error reporting are complex. The comments on the
Boost site are mostly relevant to library code; there is no
really standard way of handling internationalization, for
example, so you cannot generate language dependent messages at
the library level (unless the library assumes one particular way
of handling it, which you generally don't want). The second
point is more general. Even neglecting internationalization, if
the exception is deep in library code, it's highly unlikely that
you could create a message which would be meaningful to a user.
In such cases, the best you can do is pass enough information up
so that the application can catch the error and generate
a meaningful message in the context of what it was doing. Thus,
instead of something like "no entry 'xyz' in table", you might
want to output "Unknown type 'xyz' when deserializing data in
file 'abc'".
I started using exceptions some weeks ago and now I wonder if there is a way to just throw a warning. This warning shouldn't force the application to exit if it isn't caught. I will give you an example in what situation I would like to use that.
There is a system that appends properties to unique ids. When I somehow try to add a property to a not yet existing id, the system should create that id internally for me, add the property to it afterwards and return the result. Of course this can't be done quietly. But since the application could stay running, I do not want to throw an exception.
How can I notify that something wasn't quite correct, but the system runs on?
Who do you want to notify? The end-user? In which case, just write a suitable message to cerr. Or better, write a wrapper function (e.g. LOG_WARNING()) to do it in a controlled manner. Or better still, use a logging framework.
But since the application could stay running, I do not want to throw an exception.
Note that an exception doesn't have to result in the application terminating. You can catch an exception higher up the stack, and handle the situation appropriately.
No, that's not possible. You can only throw and catch exceptions. If you want to be cheeky you could do
class warning : public std::exception
{
public:
warning(const std::string& msg) {}
const char* what() { return msg.c_str(); } //message of warning
private:
std::string msg;
};
Then you can:
throw warning("this is a warning");
This could be an artificially made up warning system if you want.
While there's no throwing a warning. I believe the functionality you're looking for is available from errno
You can set it to any of the standard errors or make up your own error codes. (Please document them well though.)
This could be useful if your library is meant to be used by other developers. An example of when this might be useful is with a JSON parser. JSON supports arbitrarily large numbers with arbitrary accuracy. So if internally your parser uses doubles to represent numbers if it encountered a number that it couldn't represent then it could round the number to the nearest representable number the set errno=EDOM; (argument out of range) that way, it leaves the decision up to the developers as to whether the rounding will matter. If you want to be super nice you could even add in a way to retrieve the locations of the rounds possibly even with the original text.
All of that said, this should only be used in situations where:
the warning really can be bypassed completely in some scenarios
the root source of the warning is input to the library you're writing
the in some situations the consumer of the library might care about the warning but most of the time wouldn't.
there's not a more suitable way to return the information (like a status passed by reference with an overload that doesn't require the status)
Just print a message to stderr or to your logs.
When writing a function, my implementation very frequently looks like this:
Call a subfunction
If this subfunction fails to execute (because of an exceptional situation): log this failure and abort the current function
Otherwise continue calling other subfunctions, which in turn can fail
A crucial part is the logging. Every function that fails should add a short description to the log. This way, at the level where the exception is handled, the user can be shown a detailed error message.
For example, consider an application where a new user account can be created, and there is a problem with the database connection. The following inverse stack trace results:
SQLDriverConnect() -> "SQLDriverConnect error: Data source not found and no default driver specified"
OpenDatabaseConnection() -> "Failed to open database connection"
CreateUser() -> "Failed to create the new user"
ValidateAndSaveNewUserAccount() -> "Failed to save the user profile"
Catch the exception and show the logged messages to the user
Using the exceptions feature, I would implement this as follows:
void CreateUser()
{
try {
OpenDatabaseConnection();
}
catch(std::exception& e) {
e.AddLog("Failed to create the new user");
throw;
}
//...
}
Using a simple return value, I'd write the following:
bool CreateUser(Log& log)
{
if (!OpenDatabaseConnection(log))
{
log.Add("Failed to create the new user");
return false;
}
//...
return true;
}
I find both implementations equally good. Therefore, I don't see much advantage in using exceptions. I am well aware that exception handling is generally considered a useful feature, but I don't really understand why. A long time ago, I used exception handling extensively, but I didn't see the big advantage, so now I never use them anymore. Hence my questions:
Using exceptions, how can this be implemented in C++ more concisely?
If not, what is then the advantage of throwing exceptions over returning an "is successful" boolean?
Note: I use the term logging as "collecting an explanation of what went wrong, so it can be presented to the user later on". I'd rather not store that explanation in a global collection of log messages (in memory, in a file or in a database), as it directly describes the specific exception.
Update: Thanks for you responses so far. I understand that exceptions are only useful if the user doesn't need detailed feedback on what went wrong. (Please correct me if I misinterpreted this.)
Your strategy seems to avoid the most useful aspect of exceptions, you can throw an exception class which already has the text of the log information in it - that is generate the text for the log at time the exception is thrown not at the time the exception is caught. Then you don't have to catch at every level going up the stack, but only at the top level.
Thus only one try block, and one log.add - much less code in general.
Something like this seems to remove all your replication.
void OpenDatabaseConnection()
{
if (Error) throw MyException("Failed opening database");
}
void CreateUser()
{
try {
OpenDatabaseConnection();
//...... do everything here
}
catch(MyException& E) { //only one copy of this code
E.AddLog(E.getMessage());
throw;
}
}
If you always want to handle your exceptional conditions immediately after the call, then there is no real advantage.
The advantage comes when you want to handle the condition several layers up the call chain. To do that with your success flag, you'd have to bubble the flag up several layers of subroutine calls. Every layer would have to be written with the knowldege that it has to keep track of the special flag from way down in the bowels of the code. This is just a major primo PITA.
For instance, for realtime work we typically build our applications around an iteration loop. Any error during the loop generally just aborts that iteration of the loop (excepting "fatal" errors, which abort the entire app). The easiest way to handle this is to just throw exceptions from wherever they occur, and handle them all in their own catch blocks at the very outermost of the application.
I think a big case for using exceptions here is that you've now made logging part of your method signatures. In general, I don't think that should be the case, because it's a cross-cutting concern. Imagine trying to do an analogous thing with user permissions, for example. Are you going to write this everywhere?
bool CreateUser(Log& log, UserSecurityContext& u) {
if (!HasPermissionsFor(u, SecurityRoles::AddUser)) {
log.Add("Insufficient permissions");
return false;
}
//...
return true;
}
There are other reasons to want to use exceptions (see Elemental's answer), but anytime the non-use of a language feature impacts the design of your software, it's worth thinking about whether that was the right way to do it.
Exception handling removes error handling from the normal control flow. This way, the code structured more clean. Exception handling also unwinds the stack automatically. This way, you need not to include error handling code in each method called on the way to the error. If you need one of those features, go with exceptions. If you don't, use error-codes or any other method because exceptions have costs (computing time) even if they are not thrown.
Additional answers to your comment. Imagine a code, that calls several functions that may fail.
procedure exceptionTest(...)
{
try
{
call1();
call2();
call3();
call4();
}
catch (...)
{
//errorhandling outside the normal control flow
}
}
without exception:
procedure normalTest(...)
{
if (!call1())
{
//errorHandling1
}
else if (!call2())
{
//errorHandling2
}
else if ....
...
}
As you can easily see, the normal control flow is disrupted with error handling. Compared to this code, the code using exceptions is easier to read.
If you need to add error handling in each method you call, exceptions may not provide benefits. But if you have nested calls that each may generate errors, it may be easier to catch the exception at top level. That's what I meant. It is not the case in your example, still it's good to know where to benefit from exceptions.
Exceptions are using in only extreme situations. Execution of exception is too slow. For log not great errors try use return value.
Example:
int someMethod{
if(erorr_file_not_found){
logger.add("File not found");
return 1;
}
if(error_permission){
logger.add("You have not permissons to write this file");
return 2;
}
return 0;
}
In this case you can print error and process this error on higher level.
Or (more complex):
int someMethod{
int retval=0;
if(someshit){
retval=1;
goto _return;
}
//...
_return:
switch(retval){
case 1:logger.add("Situation 1");break;
case 2:logger.add("Situation 2");break;
//...
}
/*
close files, sockets, etc.
*/
return retval;
}
This way is more hard but most fast.
Depending on your circumstances, you may be able to log from a constructor of your exception (maybe asynchronously) That way your code would look like:
void CreateUser()
{
OpenDatabaseConnection();
}
Of course, you would need to throw your custom exception from OpenDatabaseConnection().
I worked on two projects when this strategy was used with success.
I would propose to separate error handling from logging and from the user interaction.
Every method can write to log files for itself. With a small log message framework, methods can output debug, informational and error message. Depending on the context your applications runs in defined by a config file, e.g., only critical error messages are actually written.
Especially in networking applications, connection failures can always occur and are not exceptional. Use exceptions for unexpected errors that should not occur or that occur only rarely. It can also make sense to use exceptions internally if you need e.g. the stack unrolling feature:
void CreateUser() {
try {
CDatabaseConnection db = ConnectToDatabase();
InsertIntoDB(db, "INSERT INTO ... ");
SetPermission(...);
} catch(...) {}
}
If InsertIntoDB throws an exception because the network connection is lost again, object CDatabaseConnection will be destroyed and SetPermission is never run. Using this can lead to better code.
The third thing you want to do is give the user feedback in an interactive application. That's a whole different thing. Let your internal methods return enumerations of possible error codes eerrorCONNECTIONLOST, eerrorUSERNAMEINVALID, etc Don't return the error strings from core methods. The user interface layer should bother which strings to display (possibly internationalizing them). Internally, the error codes will be much more useful. You could e.g. retry five times if your login method returned eerrorCONNECTIONLOST.
I've programmed C and C++ for a long time and so far I've never used exceptions and try / catch. What are the benefits of using that instead of just having functions return error codes?
Possibly an obvious point - a developer can ignore (or not be aware of) your return status and go on blissfully unaware that something failed.
An exception needs to be acknowledged in some way - it can't be silently ignored without actively putting something in place to do so.
The advantage of exceptions are two fold:
They can't be ignored. You must deal with them at some level, or they will terminate your program. With error code, you must explicitly check for them, or they are lost.
They can be ignored. If an error can't be dealt with at one level, it will automatically bubble up to the next level, where it can be. Error codes must be explicitly passed up until they reach the level where it can be dealt with.
The advantage is that you don't have to check the error code after each potentially failing call. In order for this to work though, you need to combine it with RAII classes so that everything gets automatically cleaned up as the stack unwinds.
With error messages:
int DoSomeThings()
{
int error = 0;
HandleA hA;
error = CreateAObject(&ha);
if (error)
goto cleanUpFailedA;
HandleB hB;
error = CreateBObjectWithA(hA, &hB);
if (error)
goto cleanUpFailedB;
HandleC hC;
error = CreateCObjectWithA(hB, &hC);
if (error)
goto cleanUpFailedC;
...
cleanUpFailedC:
DeleteCObject(hC);
cleanUpFailedB:
DeleteBObject(hB);
cleanUpFailedA:
DeleteAObject(hA);
return error;
}
With Exceptions and RAII
void DoSomeThings()
{
RAIIHandleA hA = CreateAObject();
RAIIHandleB hB = CreateBObjectWithA(hA);
RAIIHandleC hC = CreateCObjectWithB(hB);
...
}
struct RAIIHandleA
{
HandleA Handle;
RAIIHandleA(HandleA handle) : Handle(handle) {}
~RAIIHandleA() { DeleteAObject(Handle); }
}
...
On first glance, the RAII/Exceptions version seems longer, until you realize that the cleanup code needs to be written only once (and there are ways to simplify that). But the second version of DoSomeThings is much clearer and maintainable.
DO NOT try and use exceptions in C++ without the RAII idiom, as you will leak resources and memory. All your cleanup needs to be done in destructors of stack-allocated objects.
I realize there are other ways to do the error code handling, but they all end up looking somewhat the same. If you drop the gotos, you end up repeating clean up code.
One point for error codes, is that they make it obvious where things can fail, and how they can fail. In the above code, you write it with the assumption that things are not going to fail (but if they do, you'll be protected by the RAII wrappers). But you end up paying less heed to where things can go wrong.
Exception handling is useful because it makes it easy to separate the error handling code from the code written to handle the function of the program. This makes reading and writing the code easier.
return an error code when an error condition is expected in some cases
throw an exception when an error condition is not expected in any cases
in the former case the caller of the function must check the error code for the expected failure; in the latter case the exception can be handled by any caller up the stack (or the default handler) as is appropriate
Aside from the other things that were mentioned, you can't return an error code from a constructor. Destructors either, but you should avoid throwing an exception from a destructor too.
I wrote a blog entry about this (Exceptions make for Elegant Code), which was subsequently published in Overload. I actually wrote this in response to something Joel said on the StackOverflow podcast!
Anyway, I strongly believe that exceptions are preferable to error codes in most circumstances. I find it really painful to use functions that return error codes: you have to check the error code after each call, which can disrupt the flow of the calling code. It also means you can't use overloaded operators as there is no way to signal the error.
The pain of checking error codes means that people often neglect to do so, thus rendering them completely pointless: at least you have to explicitly ignore exceptions with a catch statement.
The use of destructors in C++ and disposers in .NET to ensure that resources are correctly freed in the presence of exceptions can also greatly simplify code. In order to get the same level of protection with error codes you either need lots of if statements, lots of duplicated cleanup code, or goto calls to a common block of cleanup at the end of a function. None of these options are pleasant.
Here's a good explanation of EAFP ("Easier to Ask for Forgiveness than Permission."), which I think applies here even if it's a Python page in Wikipedia. Using exceptions leads to a more natural style of coding, IMO -- and in the opinion of many others, too.
When I used to teach C++, our standard explanation was that they allowed you to avoid tangling sunny-day and rainy-day scenarios. In other words, you could write a function as if everything would work ok, and catch the exception in the end.
Without exceptions, you would have to get a return value from each call and ensure that it is still legitimate.
A related benefit, of course, is that you don't "waste" your return value on exceptions (and thus allow methods that should be void to be void), and can also return errors from constructors and destructors.
Google's C++ Style Guide has a great, thorough analysis of the pros and cons of exception use in C++ code. It also indicates some of the larger questions you should be asking; i.e. do I intend to distribute my code to others (who may have difficulty integrating with an exception-enabled code base)?
Sometimes you really have to use an exception in order to flag an exceptional case. For example, if something goes wrong in a constructor and you find it makes sense to notify the caller about this then you have no choice but to throw an exception.
Another example: Sometimes there is no value your function can return to denote an error; any value the function may return denotes success.
int divide(int a, int b)
{
if( b == 0 )
// then what? no integer can be used for an error flag!
else
return a / b;
}
The fact that you have to acknowledge exceptions is correct but this can also be implemented using error structs.
You could create a base error class that checks in its dtor whether a certain method ( e.g. IsOk ) has been called. If not, you could log something and then exit, or throw an exception, or raise an assert, etc...
Just calling the IsOk on the error object without reacting to it, would then be the equivalent of writing catch( ... ) {}
Both statement would display the same lack of programmer good will.
The transport of the error code up to the correct level is a greater concern. You would basically have to make almost all methods return an error code for the sole reason of propagation.
But then again, a function or method should always be annotated with the exceptions it can generate. So basically you have to same problem, without an interface to support it.
As #Martin pointed out throwing exceptions forces the programmer to handle the error. For example, not checking return codes is one of the biggest sources of security holes in C programs. Exceptions make sure that you handle the error (hopefully) and provide some kind of recover path for your program. And if you choose to ignore an exception rather than introduce a security hole your program crashes.
I'm looking for an answer in MS VC++.
When debugging a large C++ application, which unfortunately has a very extensive usage of C++ exceptions. Sometimes I catch an exception a little later than I actually want.
Example in pseudo code:
FunctionB()
{
...
throw e;
...
}
FunctionA()
{
...
FunctionB()
...
}
try
{
Function A()
}
catch(e)
{
(<--- breakpoint)
...
}
I can catch the exception with a breakpoint when debugging. But I can't trace back if the exception occurred in FunctionA() or FunctionB(), or some other function. (Assuming extensive exception use and a huge version of the above example).
One solution to my problem is to determine and save the call stack in the exception constructor (i.e. before it is caught). But this would require me to derive all exceptions from this base exception class. It would also require a lot of code, and perhaps slow down my program.
Is there an easier way that requires less work? Without having to change my large code base?
Are there better solutions to this problem in other languages?
You pointed to a breakpoint in the code. Since you are in the debugger, you could set a breakpoint on the constructor of the exception class, or set Visual Studio debugger to break on all thrown exceptions (Debug->Exceptions Click on C++ exceptions, select thrown and uncaught options)
If you are just interested in where the exception came from, you could just write a simple macro like
#define throwException(message) \
{ \
std::ostringstream oss; \
oss << __FILE __ << " " << __LINE__ << " " \
<< __FUNC__ << " " << message; \
throw std::exception(oss.str().c_str()); \
}
which will add the file name, line number and function name to the exception text (if the compiler provides the respective macros).
Then throw exceptions using
throwException("An unknown enum value has been passed!");
There's an excellent book written by John Robbins which tackles many difficult debugging questions. The book is called Debugging Applications for Microsoft .NET and Microsoft Windows. Despite the title, the book contains a host of information about debugging native C++ applications.
In this book, there is a lengthy section all about how to get the call stack for exceptions that are thrown. If I remember correctly, some of his advice involves using structured exception handling (SEH) instead of (or in addition to) C++ exceptions. I really cannot recommend the book highly enough.
Put a breakpoint in the exception object constructor. You'll get your breakpoint before the exception is thrown.
There is no way to find out the source of an exception after it's caught, unless you include that information when it is thrown. By the time you catch the exception, the stack is already unwound, and there's no way to reconstruct the stack's previous state.
Your suggestion to include the stack trace in the constructor is your best bet. Yes, it costs time during construction, but you probably shouldn't be throwing exceptions often enough that this is a concern. Making all of your exceptions inherit from a new base may also be more than you need. You could simply have the relevant exceptions inherit (thank you, multiple inheritance), and have a separate catch for those.
You can use the StackTrace64 function to build the trace (I believe there are other ways as well). Check out this article for example code.
Here's how I do it in C++ using GCC libraries:
#include <execinfo.h> // Backtrace
#include <cxxabi.h> // Demangling
vector<Str> backtrace(size_t numskip) {
vector<Str> result;
std::vector<void*> bt(100);
bt.resize(backtrace(&(*bt.begin()), bt.size()));
char **btsyms = backtrace_symbols(&(*bt.begin()), bt.size());
if (btsyms) {
for (size_t i = numskip; i < bt.size(); i++) {
Aiss in(btsyms[i]);
int idx = 0; Astr nt, addr, mangled;
in >> idx >> nt >> addr >> mangled;
if (mangled == "start") break;
int status = 0;
char *demangled = abi::__cxa_demangle(mangled.c_str(), 0, 0, &status);
Str frame = (status==0) ? Str(demangled, demangled+strlen(demangled)) :
Str(mangled.begin(), mangled.end());
result.push_back(frame);
free(demangled);
}
free(btsyms);
}
return result;
}
Your exception's constructor can simply call this function and store away the stack trace. It takes the param numskip because I like to slice off the exception's constructor from my stack traces.
There's no standard way to do this.
Further, the call stack must typically be recorded at the time of the exception being thrown; once it has been caught the stack has unrolled, so you no longer know what was going on at the point of being thrown.
In VC++ on Win32/Win64, you might get usable-enough results by recording the value from the compiler intrinsic _ReturnAddress() and ensuring that your exception class constructor is __declspec(noinline). In conjunction with the debug symbol library, I think you could probably get the function name (and line number, if your .pdb contains it) that corresponds to the return address using SymGetLineFromAddr64.
In native code you can get a shot at walking the callstack by installing a Vectored Exception handler. VC++ implements C++ exceptions on top of SEH exceptions and a vectored exception handler is given first shot before any frame based handlers. However be really careful, problems introduced by vectored exception handling can be difficult to diagnose.
Also Mike Stall has some warnings about using it in an app that has managed code. Finally, read Matt Pietrek's article and make sure you understand SEH and vectored exception handling before you try this. (Nothing feels quite so bad as tracking down a critical problem to code you added help track down critical problems.)
I believe MSDev allows you to set break points when an exception is thrown.
Alternatively put the break point on the constructor of your exception object.
If you're debugging from the IDE, go to Debug->Exceptions, click Thrown for C++ exceptions.
Other languages? Well, in Java you call e.printStackTrace(); It doesn't get much simpler than that.
In case anyone is interested, a co-worker replied to this question to me via email:
Artem wrote:
There is a flag to MiniDumpWriteDump() that can do better crash dumps that will allow seeing full program state, with all global variables, etc. As for call stacks, I doubt they can be better because of optimizations... unless you turn (maybe some) optimizations off.
Also, I think disabling inline functions and whole program optimization will help quite a lot.
In fact, there are many dump types, maybe you could choose one small enough but still having more info
http://msdn.microsoft.com/en-us/library/ms680519(VS.85).aspx
Those types won't help with call stack though, they only affect the amount of variables you'll be able to see.
I noticed some of those dump types aren't supported in dbghelp.dll version 5.1 that we use. We could update it to the newest, 6.9 version though, I've just checked the EULA for MS Debugging Tools -- the newest dbghelp.dll is still ok to redistribute.
I use my own exceptions. You can handle them quite simple - also they contain text. I use the format:
throw Exception( "comms::serial::serial( )", "Something failed!" );
Also I have a second exception format:
throw Exception( "comms::serial::serial( )", ::GetLastError( ) );
Which is then converted from a DWORD value to the actual message using FormatMessage. Using the where/what format will show you what happened and in what function.
By now, it has been 11 years since this question was asked and today, we can solve this problem using only standard C++11, i.e. cross-platform and without the need for a debugger or cumbersome logging.
You can trace the call stack that led to an exception
Use std::nested_exception and std::throw_with_nested
This won't give you a stack unwind, but in my opinion the next best thing.
It is described on StackOverflow here and here, how you can get a backtrace on your exceptions inside your code without need for a debugger or cumbersome logging, by simply writing a proper exception handler which will rethrow nested exceptions.
It will, however, require that you insert try/catch statements at the functions you wish to trace (i.e. functions without this will not appear in your trace).
You could automate this with macros, reducing the amount of code you have to write/change.
Since you can do this with any derived exception class, you can add a lot of information to such a backtrace!
You may also take a look at my MWE on GitHub, where a backtrace would look something like this:
Library API: Exception caught in function 'api_function'
Backtrace:
~/Git/mwe-cpp-exception/src/detail/Library.cpp:17 : library_function failed
~/Git/mwe-cpp-exception/src/detail/Library.cpp:13 : could not open file "nonexistent.txt"