Catching and handling all exceptions in my own class - c++

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.

Related

What should I pass to throw?

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(...).

usage of exception in c++

In my project codding i have to use a try catch method to find the function execution status.
try
{
//sample code
//calling functions
function1();
function2();
//........
}
catch(//need to catch exception)
{
return failure;
}
My requirement is that i have to catch all the exceptions that thrown from the try block
i have two options here,
catch(...)
catch(std::exception)
I think the first one will catch all the exceptions. And the second one, std::exception is the base class for all other exception classes in my program
class MyException : public std::exception
{
// All the exceptions that i have use is derived from this class
}.
Which is better and more efficient.
Is the both method works same way. Help me and suggest any method
In this case, you'd work your way through the types which may be thrown in the following order:
catch (MyException& e) {
...
}
catch (std::exception& e) {
...
}
catch (...) {
...
}
This way, you can handle the specific errors/types first, and then fall back on the weak (or untyped) handlers when the preceding handlers do not match.
Which is better and more efficient.
The order I recommended is best for handling by type. IMO, efficiency is not a concern in this scenario because correctness takes precedence and hopefully exceptions are thrown only under exceptional circumstances.
Always keep your specification as focused as possible so that you catch those that you know could be thrown, and catch derived exceptions (more specialised) before base ones:
try
{
// Some stuff
}
catch (Derived& e)
{
// Deal with specifics of Derived
}
catch (Base& e)
{
// Deal with general case of Base
}
Never use catch(...) except at the very top of your program stack (and certainly not in libraries.) When you do this, you cannot be sure about what caused the exception and therefore you cannot necessarily rely on things that you normaly would (such as memory management etc.)
I would suggest you to catch the specified exceptions only and use the catch(...) only in the main function. In my opinion the better way to use the exceptions is to implement one exception per module so each class will throw the specific exception related with the module of the class also different exceptions may be handled with a different way so I believe that
catch(const ExceptionType1& e){
}catch(const ExceptionType2& e){
}
is the better solution, also some other developer just reading this code will see which kind of exceptions could be thrown and handled....

what does "throw;" outside a catch block do?

I just stumbled this code:
void somefunction()
{
throw;
}
and I wonder: what does it mean?
The intent is probably that somefunction() is only ever called from inside some catch block. In that case, there would be an exception active when the throw; is executed, in which case the current exception is re-thrown, to be caught by the next outer handler that can handle that exception type.
If throw; is executed when an exception is not active, it calls terminate() (N4810, ยง[expr.throw]/4).
It re-throws the currently active exception. It would only make sense to call it (possibly indirectly) from a catch-block. This:
#include <iostream>
using namespace std;
void f() {
throw;
}
int main() {
try {
try {
throw "foo";
}
catch( ... ) {
f();
}
}
catch( const char * s ) {
cout << s << endl;
}
}
prints "foo".
For throw the concept of being "outside" or "inside" catch block is defined in run-time terms, not in compile-time terms as you seem to assume. So, if during run-time that throw is executed in run-time context of a catch block, then throw works as expected. Otherwise, terminate() is called.
In fact, if you take a closer look at how C++ exceptions are defined in the language specification, a lot of things about them are defined in run-time terms. Sometimes it even appears to be un-C++-like.
People have already explained what it means but it's potentially useful to know why you might see it. It's a useful way to construct a 'generic' exception handler that deals with exceptions based on their type so as to reduce the amount of duplicated code.
So, if we take Neil's example and expand on what f() might be doing we might end up with an implementation which does something like my LogKnownException() function that I proposed in this answer.
If you are working in an team that likes to log all manner of exceptions all over the place then rather than having a huge collection of catch blocks at all of these places (or even worse a macro) you can have a simple catch block that looks like this
catch(...)
{
LogKnownException();
}
Though I expect I'd change my previous example of LogKnownException() to one that simply allowed exceptions that it didn't want to log to propagate out and continue on in an unhandled fashion.
I'm not suggesting that this is necessarily a good thing to do, just pointing out that this is where you're likely to see the construct used.

What happens if I use "throw;" without an exception to throw?

Here's the setup.
I have a C++ program which calls several functions, all of which potentially throw the same exception set, and I want the same behaviour for the exceptions in each function
(e.g. print error message & reset all the data to the default for exceptionA; simply print for exceptionB; shut-down cleanly for all other exceptions).
It seems like I should be able to set the catch behaviour to call a private function which simply rethrows the error, and performs the catches, like so:
void aFunction()
{
try{ /* do some stuff that might throw */ }
catch(...){handle();}
}
void bFunction()
{
try{ /* do some stuff that might throw */ }
catch(...){handle();}
}
void handle()
{
try{throw;}
catch(anException)
{
// common code for both aFunction and bFunction
// involving the exception they threw
}
catch(anotherException)
{
// common code for both aFunction and bFunction
// involving the exception they threw
}
catch(...)
{
// common code for both aFunction and bFunction
// involving the exception they threw
}
}
Now, what happens if "handle" is called outside of the exception class.
I'm aware that this should never happen, but I'm wondering if the behaviour is undefined by the C++ standard.
If handle() is called outside the context of an exception, you will throw without an exception being handled. In this case, the standard (see section 15.5.1) specifies that
If no exception is presently being handled, executing a throw-expression with no operand calls terminate().
so your application will terminate. That's probably not what you want here.
If you use throw inside of a catch block, it will rethrow the exception. If you use throw outside of a catch block, it will terminate the application.
Never, never, never use catch(...) as you might catch application errors that you don't want to catch, e.g. bugs, access violations (depending on how you compiled).
Read the great John Robbins book (Debugging Windows Applications) in which he explains more in detail why you shouldn't do it.

Dispatching exceptions in C++

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).