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(...).
Related
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.
Why did the C++ standard bother inventing the std::exception classes? What's their benefit? My reason for asking is this:
try
{
throw std::string("boom");
}
catch (std::string str)
{
std::cout << str << std::endl;
}
Works fine. Later, if I need, I can just make my own lightweight "exception" types. So why should I bother with std::exception?
Why did the C++ standard bother inventing the std::exception classes? What's their benefit?
It provides a generic and consistent interface to handle exceptions thrown by the standard library. All the exceptions generated by the standard library are inherited from std::exception.
Note that standard library api's can throw a number of different kinds of exceptions, To quote a few examples:
std::bad_alloc
std::bad_cast
std::bad_exception
std::bad_typeid
std::logic_error
std::runtime_error
std::bad_weak_ptr | C++11
std::bad_function_call | C++11
std::ios_base::failure | C++11
std::bad_variant_access | C++17
and so on...
std::exception is the base class for all these exceptions:
providing a base class for all these exceptions, allows you to handle multiple exceptions with a common exception handler.
If I need, I can just make my own lightweight "exception" types. So why should I bother with std::exception?
If you need your custom exception class go ahead and make one. But std::exception makes your job easier because it already provides a lot of functionality which a good exception class should have. It provides you the ease of deriving from it and overidding necessary functions(in particular std::exception::what()) for your class functionality.
This gives you 2 advantages the std::exception handler,
can catch standard library exceptions as well as
exceptions of the type of your custom exception class
Image courtesy: http://en.cppreference.com/w/cpp/error/exception
Why did the C++ standard bother inventing the std::exception classes? What's their benefit?
Having different kinds of exceptions allows you to catch specific types of errors. Deriving exceptions from a common base allows for granularity in catching more generic or specific errors depending on circumstance.
In C++ an existing type system is already in place, so standardizing error strings was unnecessary when you can explicitly create an exception of a desired type in the language.
std::exception and its derived classes exist for two main reasons:
The standard library has to have some kind of exception hierarchy to
throw in exceptional circumstances. It would be inappropriate to
always throw an std::string because you would have no clean way to
target specific kinds of errors.
To provide an extensible class based interface for library vendors to throw the most basic error types and provide a common fallback for users. You may want to provide more error metadata than a simple what() string so that the person catching your error can more intelligently recover from it.
At the same time std::exception as a common base allows a general catchall less all-encompassing than ... if the user only cares about that error message.
If all you ever do is print and quit then it doesn't really matter, but you may as well use std::runtime_error which inherits from std::exception for catch convenience.
Later, if I need, I can just make my own lightweight "exception" types. So why should I bother with std::exception?
If you inherit from std::runtime_error and use your own custom error type then you can retroactively add error metadata without having to rewrite catch blocks! In contrast, if you ever changed your error handling design then you would be forced to rewrite all your std::string catches because you cannot safely inherit from std::string. It is not a forward-looking design decision.
If that doesn't seem so bad right now, imagine if your code were to become shared across multiple projects as a shared library with various programmers working on it. Migrating to the new version of your library would become a pain.
This isn't even mentioning that std::string can throw its own exceptions during copy, construction, or access of characters!
Boost's website has some good guidelines in exception handling and class construction here.
User Story
I am writing some network code and using a third party vendor's
library. On an invalid ip address being entered by the user this
library throws a custom exception nw::invalid_ip derived from
std::runtime_error. nw::invalid_ip contains a what() describing
the error message, but also the incorrect_ip() address supplied.
I also use std::vector to store sockets, and am making use of the
checked at() call to safely access indices. I know that if I
call at() on a value out of bounds std::out_of_range is thrown.
I know other things may be thrown as well, but I do not know how to
handle them, or what exactly they might be.
When I get an nw::invalid_ip error I pop up a modal with an input
box for the user populated with the invalid ip address so they can edit
it and try again.
For std::out_of_range issues, I respond by running an integrity check
on the sockets and fixing the vector/socket relationship that has fallen
out of synch.
For any other std::exception issues I terminate the program with an
error log. Finally I have a catch(...) which logs "unknown error!" and
terminates.
It would be difficult to robustly do this with only std::string being thrown.
Here's a basic example of a few things being thrown in different cases so you can play with catching exceptions.
ExampleExceptions.cpp
#include <vector>
#include <iostream>
#include <functional>
#include <stdexcept>
#include <bitset>
#include <string>
struct Base1 {
virtual ~Base1(){}
};
struct Base2 {
virtual ~Base2(){}
};
class Class1 : public Base1 {};
class Class2 : public Base2 {};
class CustomException : public std::runtime_error {
public:
explicit CustomException(const std::string& what_arg, int errorCode):
std::runtime_error(what_arg),
errorCode(errorCode){
}
int whatErrorCode() const {
return errorCode;
}
private:
int errorCode;
};
void tryWrap(typename std::function<void()> f){
try {
f();
} catch(CustomException &e) {
std::cout << "Custom Exception: " << e.what() << " Error Code: " << e.whatErrorCode() << std::endl;
} catch(std::out_of_range &e) {
std::cout << "Range exception: " << e.what() << std::endl;
} catch(std::bad_cast &e) {
std::cout << "Cast exception: " << e.what() << std::endl;
} catch(std::exception &e) {
std::cout << "General exception: " << e.what() << std::endl;
} catch(...) {
std::cout << "What just happened?" << std::endl;
}
}
int main(){
Class1 a;
Class2 b;
std::vector<Class2> values;
tryWrap([](){
throw CustomException("My exception with an additional error code!", 42);
});
tryWrap([&](){
values.at(10);
});
tryWrap([&](){
Class2 c = dynamic_cast<Class2&>(a);
});
tryWrap([&](){
values.push_back(dynamic_cast<Class2&>(a));
values.at(1);
});
tryWrap([](){
std::bitset<5> mybitset (std::string("01234"));
});
tryWrap([](){
throw 5;
});
}
Output:
Custom Exception: My exception with an additional error code! Error Code: 42
Range exception: vector::_M_range_check
Cast exception: std::bad_cast
Cast exception: std::bad_cast
General exception: bitset::_M_copy_from_ptr
What just happened?
It's a legitimate question because std::exception only really contains a single property: what(), a string. So it's tempting to just use string instead of exception. But the fact is that an exception is not a string. If you treat an exception like it's merely a string, you lose the ability to derive from it in specialized exception classes that would provide more properties.
For example today you throw strings in your own code. Tomorrow you decide to add more properties to certain cases like a database connection exception. You can't just derive from string to make this change; you will need to write a new exception class and change all the exception handlers for string. Using exception is a way for exception handlers to use only the data they care about, to pick and choose exceptions as they need to handle them.
Also if you throw and handle only string-typed exceptions, you will miss all exceptions thrown from any code that's not your own. If this distinction is intentional, it would be best described by using a common exception class to signify this, not the generic type of string.
exception is also more specific than string. This means library developers can write functions that accept exceptions as parameters, which is clearer than accepting a string.
All of this is essentially free, just use exception instead of string.
Just because something "works fine" in a 6 line toy example doesn't mean it is scalable or maintainable in real code.
Consider this function:
template<typename T>
std::string convert(const T& t)
{
return boost:lexical_cast<std::string>(t);
}
This could throw bad_alloc if memory for the string cannot be allocated, or could throw bad_cast if the conversion fails.
A caller of this function might want to handle the failed conversion case which indicates bad input but isn't a fatal error, but not want to handle the out-of-memory case, because they can't do anything about it so let the exception propagate up the stack. This is very easy to do in C++, for example:
std::string s;
try {
s = convert(val);
} catch (const std::bad_cast& e) {
s = "failed";
}
If exceptions were just thrown as std::string the code would have to be:
std::string s;
try {
s = convert(val);
} catch (const std::string& e) {
if (e.find("bad_cast") != std::string::npos)
s = "failed";
else
throw;
}
This takes more code to implement and relies on the exact wording of the exception string, which might depend on the compiler implementation and the definition of boost::lexical_cast. If every piece of exception handling in the system had to do string comparisons to decide if the error can be handled at that point it would be messy and unmaintainable. A small change to the spelling of an exception message in one part of the system that throws exceptions might cause the exception handling code in another part of the system to stop working. This creates tight coupling between the location of an error and every bit of error handling code in the system. One of the advantages of using exceptions is to allow error handling to be separated from the main logic, you lose that advantage if you create dependencies based on string comparisons across the whole system.
Exception handling in C++ catches things by matching on the exception's type, it doesn't catch by matching on an exception's value, so it makes sense to throw things of different types to allow fine-grained handling. Throwing things of a single string type and handling them based on the string's value is messy, non-portable and more difficult.
Later, if I need, I can just make my own lightweight "exception" types. So why should I bother with std::exception?
If your code is useful and reusable and I want to use it in part of my system, do I have to add exception handling that catches all your lightweight types? Why should the whole of my system care about the internal details of a library that one bit of the system relies on? If your custom exception types are derived from std::exception then I can catch them by const std::exception& without knowing (or caring) about the specific types.
If you are the only user of the class,you can avoid std::exception(if you want to avoid the standard library exceptions)
But if your class is going to be used by others (programmers),how would they handle the exception.
If your class throws a string that describes the error,that would not help since the consumers of your class would prefer a more standard way(catch an exception object and query it's what method) to handle the exception rather than catching a string..
Also you can catch exceptions thrown by the standard library by catching an exception object
You can override the what method of exception class to give more information about the error.
Wow, I'm surprised no one mentioned this:
You need multiple types of exceptions in order to be able to distinguish them -- some kinds of exceptions should be handled, while others shouldn't.
They need to have a common base class to allow you to have a means for displaying a sane message to the user without having to know all the types of exceptions that your program could possibly throw (which is impossible when using external closed source libraries).
1) For convenience I have my entire program in a try block. This way I can throw an exception at any point in my code and know that it will be handled the same way. As the program becomes larger will this technique cause a hit in performance?
2) If objects are de-allocated when out of scope, why would throwing a temporary object be valid? e.g.:
class Error : public std::exception
{
private:
char *m;
private:
Error(char *l) : m(l) {}
virtual char *what()
{
return m;
}
};
int main()
{
try
{
throw Error("test");
}
catch(std::exception &e)
{
puts(e.what());
return -1;
}
return 0;
}
In the throw statement, why wouldn't the temporary object become invalid since it's been declared only in the try scope?
3) With Windows operating systems of a language other than English, would the what() member of the STL exception class still return a char* string? Or could it return a wchar_t* string?
Technically you don't throw the actual object, you throw a copy of it. That's why you can get away with throwing a temporary. Catching a reference also gets a reference to the copy.
This can bite you if you rethrow an exception from within a catch block, you can fall victim to the slicing problem. That's why you don't do:
catch (std::exception & e)
{
throw e; // bad, always throws std::exception rather than what was caught
}
But rather
catch (std::exception & e)
{
throw; // good, rethrows the exact copy that you caught without making another copy
}
P.S. There's no rule saying you couldn't return a UTF-8 string from what. It would be up to you to convert it to UTF-16 for Windows I/O. The standard exception classes were never explicitly designed or extended for Unicode, nor are any non-standard extensions added just for Windows.
1)
Having the whole program in a try block will not incur any performance hit, apart from that incurred by having exceptions enabled at all
2)
It is OK because you are throwing by value. Throwing by value means that whatever you throw is copied when thrown. So throwing any temporary is perfectly valid because a copy is made.
3)
The std::exception class, as far as I can determine, can only ever throw a char*. However you could always subclass it and implement support for wchar if you wanted.
It is worth noting that you shouldn't just have a try catch around main() if that is what you were intending.
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).
In C++, I'm trying to catch all types of exceptions in one catch (like catch(Exception) in C#). How is it done? And what's more, how can one catch divide-by-zero exceptions?
catch (...)
{
// Handle exceptions not covered.
}
Important considerations:
A better approach is to catch specific types of exception that you can actually recover from as opposed to all possible exceptions.
catch(...) will also catch certain serious system level exceptions (varies depending on compiler) that you are not going to be able to recover reliably from. Catching them in this way and then swallowing them and continuing could cause further serious problems in your program.
Depending on your context it can be acceptable to use catch(...), providing the exception is re-thrown. In this case, you log all useful local state information and then re-throw the exception to allow it to propagate up. However you should read up on the RAII pattern if you choose this route.
You don't want to be using catch (...) (i.e. catch with the ellipsis) unless you really, definitely, most provable have a need for it.
The reason for this is that some compilers (Visual C++ 6 to name the most common) also turn errors like segmentation faults and other really bad conditions into exceptions that you can gladly handle using catch (...). This is very bad, because you don't see the crashes anymore.
And technically, yes, you can also catch division by zero (you'll have to "StackOverflow" for that), but you really should be avoiding making such divisions in the first place.
Instead, do the following:
If you actually know what kind of exception(s) to expect, catch those types and no more, and
If you need to throw exceptions yourself, and need to catch all the exceptions you will throw, make these exceptions derive from std::exception (as Adam Pierce suggested) and catch that.
If you are on windows and need to handle errors like divide by zero and access violation you can use a structured exception translator. And then inside of your translator you can throw a c++ exception:
void myTranslator(unsigned code, EXCEPTION_POINTERS*)
{
throw std::exception(<appropriate string here>);
}
_set_se_translator(myTranslator);
Note, the code will tell you what the error was. Also you need to compile with the /EHa option (C/C++ -> Code Generatrion -> Enable C/C++ Exceptions = Yes with SEH Exceptions).
If that doesn't make sense checkout the docs for [_set_se_translator](http://msdn.microsoft.com/en-us/library/5z4bw5h5(VS.80).aspx)
If catching all exceptions - including OS ones - is really what you need, you need to take a look at your compiler and OS. For example, on Windows you probably have "__try" keyword or compiler switch to make "try/catch" catch SEH exceptions, or both.
Make all your custom exception classes inherit from std::exception, then you can simply catch std::exception. Here is some example code:
class WidgetError
: public std::exception
{
public:
WidgetError()
{ }
virtual ~WidgetError() throw()
{ }
virtual const char *what() const throw()
{
return "You got you a widget error!";
}
};
In C++, the standard does not define a divide-by-zero exception, and implementations tend to not throw them.
You can, of course, use catch (...) { /* code here */ }, but it really Depends On What You Want To Do. In C++ you have deterministic destructors (none of that finalisation rubbish), so if you want to mop up, the correct thing to do is to use RAII.
For example. instead of:
void myfunc()
{
void* h = get_handle_that_must_be_released();
try { random_func(h); }
catch (...) { release_object(h); throw; }
release_object(h);
}
Do something like:
#include<boost/shared_ptr.hpp>
void my_func()
{
boost::shared_ptr<void> h(get_handle_that_must_be_released(), release_object);
random_func(h.get());
}
Create your own class with a destructor if you don't use boost.
You can use catch(...) to catch EVERYTHING, but then you don't get a an object to inspect, rethrow, log, or do anything with exactly. So... you can "double up" the try block and rethrow into one outer catch that handles a single type. This works ideally if you define constructors for a custom exception type that can build itself from all the kinds you want to group together. You can then throw a default constructed one from the catch(...), which might have a message or code in it like "UNKNOWN", or however you want to track such things.
Example:
try
{
try
{
// do something that can produce various exception types
}
catch( const CustomExceptionA &e ){ throw e; } \
catch( const CustomExceptionB &e ){ throw CustomExceptionA( e ); } \
catch( const std::exception &e ) { throw CustomExceptionA( e ); } \
catch( ... ) { throw CustomExceptionA(); } \
}
catch( const CustomExceptionA &e )
{
// Handle any exception as CustomExceptionA
}
If I recall correctly (it's been a while since I've looked at C++), I think the following should do the trick
try
{
// some code
}
catch(...)
{
// catch anything
}
and a quick google(http://www.oreillynet.com/pub/a/network/2003/05/05/cpluspocketref.html) seems to prove me correct.