How should exceptions be dispatched so that error handling and diagnostics can be handled in a centralized, user-friendly manner?
For example:
A DataHW class handles communication with some data acquisition hardware.
The DataHW class may throw exceptions based on a number of possible errors: intermittent signal, no signal, CRC failure, driver error. Each type of error gets its own exception class.
The DataHW class is called by a number of different pieces of code that do different types of acquisition and analysis.
The proper error handling strategy depends on the type of exception and the operation being attempted. (On intermittent signal, retry X times then tell the user; on a driver error, log an error and restart the driver; etc.) How should this error handling strategy be invoked?
Coding error recovery into each exception class: This would result in exception classes that are rather large and contain high-level UI and system management code. This seems bad.
Providing a separate catch block for each type of exception: Since the DataHW class is called from many different places, each catch block would have to be duplicated at each call site. This seems bad.
Using a single catch block that calls some ExceptionDispatch function with a giant RTTI-based switch statement: RTTI and switch usually indicates a failure to apply OO design, but this seems the least bad alternative.
Avoid duplicating the catch blocks at each call site by catching (...) and calling a shared handler function which rethrows and dispatches:
f()
{
try
{
// something
}
catch (...)
{
handle();
}
}
void handle()
{
try
{
throw;
}
catch (const Foo& e)
{
// handle Foo
}
catch (const Bar& e)
{
// handle Bar
}
// etc
}
An idea I keep running into is that exceptions should be caught by levels which can handle them. For example, a CRC error might be caught by the function that transmits the data, and upon catching this exception, it might try to retransmit, whereas a "no signal" exception might be caught in a higher level and drop or delay the whole operation.
But my guess is that most of these exceptions will be caught around the same function. It is a good idea to catch and handle them seperately (as in soln #2), but you say this causes a lot of duplicate code (leading to soln #3.)
My question is, if there is a lot of code to duplicate, why not make it into a function?
I'm thinking along the lines of...
void SendData(DataHW* data, Destination *dest)
{
try {
data->send(dest);
} catch (CRCError) {
//log error
//retransmit:
data->send(dest);
} catch (UnrecoverableError) {
throw GivingUp;
}
}
I guess it would be like your ExceptionDispatch() function, only instead of switching on the exception type, it would wrap the exception-generating call itself and catch the exceptions.
Of course, this function is overly simplified - you might need a whole wrapper class around DataHW; but my point is, it would be a good idea to have a centralized point around which all DataHW exceptions are handled - if the way different users of the class would handle them are similar.
Perhaps you could write a wrapper class for the DataHW class?
The wrapper would offer the same functionality as the DataHW class, but also contained the needed error handling code. Benefit is that you have the error handling code in a single place (DRY principle), and all errors would be handled uniformly. For example you can translate all low level I/O exceptions to higher level exceptions in the wrapper.
Basically preventing low level exceptions being showed to user.
As Butler Lampson said: All problems in computer science can be solved by another level of indirection
There are three ways i see to solve this.
Writing wrapper functions
Write a wrapper function for each function that can throw exceptions which would handle exceptions. That wrapper is then called by all the callers, instead of the original throwing function.
Using function objects
Another solution is to take a more generic approach and write one function that takes a function object and handles all exceptions. Here is some example:
class DataHW {
public:
template<typename Function>
bool executeAndHandle(Function f) {
for(int tries = 0; ; tries++) {
try {
f(this);
return true;
}
catch(CrcError & e) {
// handle crc error
}
catch(IntermittentSignalError & e) {
// handle intermittent signal
if(tries < 3) {
continue;
} else {
logError("Signal interruption after 3 tries.");
}
}
catch(DriverError & e) {
// restart
}
return false;
}
}
void sendData(char const *data, std::size_t len);
void readData(char *data, std::size_t len);
};
Now if you want to do something, you can just do it:
void doit() {
char buf[] = "hello world";
hw.executeAndHandle(boost::bind(&DataHW::sendData, _1, buf, sizeof buf));
}
Since you provide function objects, you can manage state too. Let's say sendData updates len so that it knows how much bytes were read. Then you can write function objects that read and write and maintain a count for how many characters are read so far.
The downside of this second approach is that you can't access result values of the throwing functions, since they are called from the function object wrappers. There is no easy way to get the result type of a function object binder. One workaround is to write a result function object that is called by executeAndHandle after the execution of the function object succeeded. But if we put too much work into this second approach just to make all the housekeeping work, it's not worth the results anymore.
Combining the two
There is a third option too. We can combine the two solutions (wrapper and function objects).
class DataHW {
public:
template<typename R, typename Function>
R executeAndHandle(Function f) {
for(int tries = 0; ; tries++) {
try {
return f(this);
}
catch(CrcError & e) {
// handle crc error
}
catch(IntermittentSignalError & e) {
// handle intermittent signal
if(tries < 3) {
continue;
} else {
logError("Signal interruption after 3 tries.");
}
}
catch(DriverError & e) {
// restart
}
// return a sensible default. for bool, that's false. for other integer
// types, it's zero.
return R();
}
}
T sendData(char const *data, std::size_t len) {
return executeAndHandle<T>(
boost::bind(&DataHW::doSendData, _1, data, len));
}
// say it returns something for this example
T doSendData(char const *data, std::size_t len);
T doReadData(char *data, std::size_t len);
};
The trick is the return f(); pattern. We can return even when f returns void. This eventually would be my favorite, since it allows both to keep handle code central at one place, but also allows special handling in the wrapper functions. You can decide whether it's better to split this up and make an own class that has that error handler function and the wrappers. Probably that would be a cleaner solution (i think of Separation of Concerns here. One is the basic DataHW functionality and one is the error handling).
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.
I have a C++ API which throws exceptions in error conditions. Usually, the method I have seen in C++ APIs to notify errors is by special return codes and functions which returns last error string which can be checked if method returns an error code. This method has limitations, for example if you need to return an integer from a function and the whole integer value range is valid for return values so you can't return an error code.
Due to this, I choose to throw an exception in my API when an error occurs in a function.
Is this an acceptable usage of exceptions in C++?
Also, In some functions in my API (eg. authenticate()), I have two options.
return bool to indicate success.
return void and throw an exception if failed.
If first option is used, it is not consistent with other functions because they all throw exceptions. Also, it is difficult to indicate what is the error.
So is it ok to use second method in such functions too?
In following answer, it is mentioned that it is bad to use C++ exceptions for controlling program flow. Also, I have heard the same elsewhere too.
https://stackoverflow.com/a/1736162/1015678
Does my usage violates this? I cannot clearly identify whether I am using exceptions for controlling program flow here.
the method I have seen in C++ APIs to notify errors is by special return codes and functions which returns last error string which can be checked if method returns an error code.
Sometimes that's done for good reasons, but more often when you see that the C++ library wraps an older C library, has been written by someone more comfortable with C, written for client coders more comfortable with C, or is written for interoperability with C.
return an integer from a function and the whole integer value range is valid for return values so you can't return an error code.
Options include:
exceptions
returning with a wider type (e.g. getc() returns an int with -1 indicating EOF).
returning a success flag alongside the value, wrapped in a boost::optional, pair, tuple or struct
having at least one of the success flag and/or value owned by the caller and specified to the function as a non-const by-reference or by-pointer parameter
Is this an acceptable usage of exceptions in C++?
Sounds ok, but the art is in balancing the pros and cons and we don't know whether it's optimally convenient and robust for client code calling your functions. Understanding their expectations in key, which will partly be formed based on their overall C++ experience, but also from the rest of your API and any other APIs shipped alongside yours, and even from other APIs for other libraries they're likely to be using in the same apps etc..
Consider too whether the caller of a function is likely to want to handle the success or failure of that function in the context of the call, separately from other possible failures. For example, sometimes it's easier for client code to work with functions returning boolean success values:
if (fn(1) && !fn(2))
fn(3);
try
{
fn(1);
try
{
fn2();
}
catch (const ExpectedExceptionFromFn2Type&)
{
fn3();
}
}
catch (const PossibleExceptionFromFn1Type&)
{
// that's ok - we don't care...
}
But other times it can be easier with exceptions:
try
{
My_X x { get_X(99) };
if (x.is_happy(42))
x += next_prime_after(x.to_int() * 3);
}
catch (std::exception& e)
{
std::cerr << "oops\n";
}
...compared to...
bool success;
My_X x;
if (get_X(&x, 99)) {
if (x.is_valid() {
bool happy;
if (x.can_get_happy(&happy, 42) && happy) {
int my_int;
if (x.can_convert_to_int(&my_int)) {
if (!x.add(next_prime_after(x.to_int() * 3))) {
std::cerr << "blah blah\n";
return false;
} else { cerr / return false; }
} else { cerr / return false; }
} else { cerr / return false; }
} else { cerr / return false; }
} else { cerr / return false; }
(Exactly how bad it gets depends on whether functions support reporting an error, or can be trusted to always work. That's difficult too, because it something happens that makes it possible for a function to start failing (e.g. it starts using a data file that could potentially be missing), if client code didn't already accept and check an error code or catch exceptions, then that client code may need to be reworked once the potential for errors is recognised. That's less true for exceptions, which - when you're lucky - may propagate to some already-suitable client catch statement, but on the other hand it's a risky assuming so without at least eyeballing the client code.)
Once you've considered whatever you know about client usage, there may still be some doubt about which approach is best: often you can just pick something and stick to it throughout your API, but occasionally you may want to offer multiple versions of a function, e.g.:
bool can_authenticate();
void authenticate_or_throw();
...or...
enum Errors_By { Return_Value, Exception };
bool authenticate(Errors_By e) { ... if (e == Exception) throw ...; return ...; }
...or...
template <class Error_Policy>
struct System
{
bool authenticate() { ... Error_Policy::return_or_throw(...); }
...
}
Also, In some functions in my API (eg. authenticate()), I have two options.
As above, you have more than 2 options. Anyway, consistency is very important. It sounds like exceptions are appropriate.
mentioned that it is bad to use C++ exceptions for controlling program flow
That is precisely what exceptions do and all they can be used for, but I do understand what you mean. Ultimately, striking the right balance is an art that comes with having used a lot of other software, considering other libraries your clients will be using alongside yours etc.. That said, if something is an "error" in some sense, it's at least reasonable to consider exceptions.
For something like authenticate(), I'd expect you to return a bool if you were able to compute a true/false value for the authentication, and throw an exception if something prevented you from doing that. The comment about using exceptions for flow control is suggesting NOT doing something like:
try {
...
authenticate();
// rely on the exception to not execute the rest of the code.
...
} catch (...) { ... }
For instance, I can imagine an authenticate() method that relies on contacting some service, and if you can't communicate with that service for some reason, you don't know if the credentials are good or bad.
Then again, the other major rule of thumb for APIs is "be consistent". If the rest of the API relies on exceptions to serve as the false value in similar cases, use that, but to me, it's a little on the ugly side. I'd lean toward reserving exceptions for the exceptional case - i.e. rare, shouldn't ever happen during normal operations, cases.
I need to stop the program flow in the middle, and I am currently using an exception for this. This flow is the legal flow and I want to know if I can do it without using an exception.
This is an example of my code, and I cannot change func_2 and func_1:
#include "stdio.h"
void func_3()
{
printf("i am func_3\n");
throw 20;
printf("i am not supposed to be here\n");
}
void func_2()
{
printf("i am func_2\n");
func_3();
printf("i am not supposed to be here\n");
}
void func_1()
{
printf("i am func_1\n");
func_2();
printf("i am not supposed to be here\n");
}
int main()
{
try
{
func_1();
}
catch (int e)
{
printf("i am supposed to be here\n");
}
catch (...)
{
printf("i am not supposed to be here\n");
}
}
I assume that you want to handle an exceptional case and are looking for an alternative to exceptions. I.e. I hope you don't want to continue with the program "normally" after handling your exceptional case, which is possible but not recommended to implement with exceptions.
Possible but not recommended alternatives to exceptions are:
When you want to stop your whole application, then you can use std::exit(0);. You can implement your "catch"-code in a function which you call instead of your "throw"-statement, and call std::exit(0); at the end of that function (or use another exit code to indicate an "unsuccessful" exit). Or you implement an exit handler and register it using std::atexit(&handle_exit);.
Alternative to std::exit(<something>); is abort(); which throws the POSIX signal "SIGABRT" to indicate abnormal termination (which is the default behavior if your program throws and doesn't catch an exception). Your "catch"-code would then go in a signal handler which you register using the POSIX functions. Note that this requires a POSIX system and is thus not as portable as other solutions.
Another (similar) option is to use the "terminate" mechanism: Call std::terminate(); when you would normally throw your exception. Put your "catch"-code in a "terminate handler" function with signature void(*)(), i.e. no parameters and no return value, let's call the function void handle_terminate(). Install a terminate handler using std::set_terminate(&handle_terminate);. I didn't try that one, however, and it sounds damn ugly.
You could implement an exception-like behavior using assembly instructions, but please do not try this at home, as the behavior of such code is highly implementation defined (if not undefined), and way too ugly to implement.
In short, you can't (well ... you could, by using jumps instead, but then you would have two problems to solve).
The exception solution is the one to use, but do not throw a number (a number - especially a magical number in this case doesn't tell you anything).
Instead, define a struct func_3_interrupted {}; minimalistic structure, whose type name tells you it is an "interruption" of func_3, and catch that instead; The structure should be empty (or close to empty) and it should probably not inherit from the std::exception hierarchy.
Return can be used to return to the caller and stop the function being executed
int GLOBAL_FLAG = 1;
function called_function(){
printf("Inside Function")
if(/*some condition*/)
{
GLOBAL_FLAG = 0;
return;
}
/*Normal function code*/
}
int main(){
{
called_function();
if(GLOBAL_FLAG == 1)/*continue program execution*/
printf("Function had been executed.Back to normal flow")
}
So once the return statement is encountered it goes back to the caller that is main here and continues executing rest of the statements in main function.
I added a bunch of exceptions to my hash table class to deal with various issues that might come up. They are mostly constructed like this:
std::string msg = std::string("I made doodoo, some value: ") + std::tostring(value);
throw std::exception(msg.c_str());
Some of the exceptions are part of normal operation, for example there is one that says the table is full and the thing that catches it then rebuilds the table into a bigger one. I discovered that this puts a sizable dent in the performance though, I suspect its all the string construction. At the same time though, I want the exceptions to be meaningful and make sense to somebody who doesn't know what the code numbers I come up with mean. Whats a good way to deal with this?
Ideally you should be creating custom exception classes from std::exception. That way when you create your catch blocks, you can have a specific catch for each of your exceptions. Example:
class MyException; // Inherits from std::exception.
class MyOtherException; // Inherits from std::exception.
void foo()
{
if (bar)
throw MyException();
if (baz)
throw MyOtherException();
// do stuff.
}
int main()
{
try
{
foo();
}
catch(const MyException &ex)
{
// Handle MyException.
}
catch (const MyOtherException &ex)
{
// Handle MyOtherException.
}
}
Creating your own exception classes affords you a lot more flexibility because it allows you to attach additional information to your exceptions, as well as handling different exception types as described above.
class MyException : public std::exception
{
private:
std::string m_description;
int m_userId;
public:
MyException(const std::string &errorDescription = "Unhandled exception", const int userId) :
m_description(errorDescription),
m_userId(userId)
{
}
int get_user_id() const
{
return m_userId;
}
virtual const char *what() const
{
return m_description.c_str();
}
}
The main problem with your code (at least how you described it) however is that you seem to be controlling your program flow with exceptions. Exceptions are not designed to be fast constructs, they're designed for exceptional cases that would, if not handled, cause your program to crash. Attempting to use exceptions in place of if statements is going to make your code very slow, very hard to read, and even harder to understand/maintain.
To take from your example: if you're adding to a hash table, and need to resize the table, why do you need to throw an exception, when you could just resize it? This is exactly how an std::vector works. If you do a push_back() on a vector and vector.capacity() < vector.size() + 1, the vector will internally re-allocate the buffer so that the new item can be added. The only time an exception might be thrown is if you run out of memory. The caller isn't aware of any of this, it just calls vector.push_back(...).
Hello to all and sorry for my english!
How can I do the title above?
For example, I have a class contains a some functions that can throw exceptions:
class cl {
public:
void f1();
void f2();
};
void cl::f1()
{
// throw exception
}
void cl::f2()
{
// throw exception
}
I need to handle them.
Are there any other method to handle exceptions (that throws in my class) in one place of the code except code like this:
void cl::f1()
{
try
{
// throw exception
}
catch (...)
{
// handling
}
}
void cl::f1()
{
try
{
// throw exception
}
catch (...)
{
// handling
}
}
or this:
int main()
{
cl c;
try
{
f1();
f2();
}
catch(...)
{
// handling
}
}
?
Thanks in advance!
Are there any other method to handle exceptions (that throws in my
class) in one place of the code except code like this:
In my opinion you would typically only handle an exception when:
You can remedy it i.e do something about it e.g allow the user to select a different file.
You can add additional information.
For the latter case, it would mean throwing a new exception (possible of different type) from the handler.
If neither of the above hold, let it propagate to a level where it can be handled. In your case, I would not have a try/catch within f1 and f2, but only at the callsite (in main).
You might ask whether one cannot(should not) do certain cleanup work in the catch handler. I personally have never found this to be necessary if/when one uses the stack/scope to clean up see RAII. I/we usually have one catch handler per thread at the highest level, and this simply performs logging. We catch (and use exceptions) for runtime errors mostly. For logic errors we use assert (even in release mode), but this can be (and have been) debated often.