C++ nested method try catch (practices) - c++

I'm new to C++ (coming from C) and writing a class B that is a member of another class A.
The member B will throw an exception if the parent tries to access data that does not exist from B's container (I throw an invalid_argument exception). The member B has an object that can be thought of like an STL container, so it will be for this example.
My question is: if I catch the original invalid_parameter exception in A, is it considered good C++ practice to re-throw the same exception (I'd re-throw the original error, but I do some logging in it, so the what() is different), or can I just throw std::exception. My code now has many
try { A.calls_b_exception } catch (std::invalid_argument& ie) {...} catch (std::exception& e) {...}
blocks and I was wondering if I could reduce them to
try { A.calls_b_exception } catch (std::exception& e) {...}
and still be following good C++ paradigms.
Example code that is similar to my situation:
class B
{
std::vector<int> stuff;
int get_value(int index)
{
if (index >= stuff.size()) {
stringstream err;
err << "--> invalid index " << index << " for stuff";
throw std::invalid_argument(err.str());
}
}
}
class A
{
B b;
// Assume there are methods to add a bunch of stuff to B
int get_value(int index)
{
try {
b.get_value();
} catch (std::invalid_argument& ie) {
stringstream err;
err << ie.what() << "\n\t--> A::get_value(" << index << ")";
// should I throw the same exception here or is this considered good C++ etiquette?
throw std::exception(err.str());
} catch (std::exception& e) {
throw; // something I was not anticipating handling happened
}
}
}
int main
{
A a;
// Assume more stuff to add to A
try {
a.get_value(-1);
}
catch (std::exception& e) {
stringstream err;
err << "--> invalid index " << index << " for main";
throw std::exception(err.str());exception here?
}
}

You cannot instantiate std::exception(std::string), so my initial approach will not work.
Thanks to those of you who took time to read through my question and help me out.

Related

In a C++ command-line application, how should I catch exceptions at the top-level?

I am writing a command-line application in C++. If an unhandled exception occurs, I don't want the app to crash badly, but to clean up as well as possible and print an error message.
How should I catch exceptions at the top-level in order to avoid the program crashing? Should I catch std::exception, ... or something else?
The quality of the cleaning you can do is a function of the exception being thrown.
For example, an exception that you raise yourself (perhaps derived from std::exception; let's call it fooexception) could well be handled quite elegantly.
So really you want a catch site on these lines
try {
/*whatever*/
} catch (fooexception& fe){
/*ToDo - handle my exception*/
} catch (std::exception& e){
/*ToDo - handle this generically*/
} catch (...){
/*Hum. That's bad. Let's do my best*/
}
Extend this at your leisure. Just remember that in a sense, multiple catch blocks behave like if else blocks: always order with the specific exceptions first.
Well, you could catch both:
int main() {
try {
// do stuff
}
catch(const std::exception& e) {
std::cout << "Caught exception: " << e.what() << std::endl;
}
catch(...) {
std::cout << "Caught unknown exception." << std::endl;
}
}
You should catch both, and possibly more. If you use a more specific exception type somewhere in the call stack, try to catch that as well.
Consider the code:
try
{
process();
}
catch (const SpecificException& ex)
{
std::cerr << "SpecificException occured: " << ex.what() << std::endl;
}
catch (const std::runtime_error& ex)
{
std::cerr << "std::runtime_error occured: " << ex.what() << std::endl;
}
catch (...)
{
std::cerr << "Unknown error occured!" << std::endl; // should never happen hopefully
}
And remember to always sort by specificness of exceptions - the more specialized/derived first, as the runtime will stop at the first catch block able to process the exception (i.e. first catch block with exception type matching or being a base of).

How to catch all custom exceptions in a single catch statement with Apache Thrift?

I have many different exceptions defined in exception.thrift:
exception InvalidArgumentsError {
1: string parameter
}
/**
* Server has an problem while executing a function.
* Execution aborted.
*/
exception ServerInternalError {
1: string parameter
}
/**
* Server answer is empty.
*/
exception NoDataError {
1: string parameter
}
This is how i catch them in my C++ code:
catch (InvalidArgumentsError & ex) {
std::cout << ex.parameter;
}
catch (ServerInternalError & ex) {
std::cout << ex.parameter;
}
catch (NoDataError & ex) {
std::cout << ex.parameter;
}
catch (apache::thrift::TException& ex) {
std::cout << "TException:\n" << ex.what();
} catch (const std::exception& ex) {
std::cout << ex.what();
return;
}
I want to write something like this and catch all my exceptions:
catch (SomeBasicException& ex) {
std::cout << ex.what();
}
catch (const std::exception& ex) {
std::cout << ex.what();
}
If I just catch TException and call what() I just get 'Default TException' message because derived classed do not override virtual what() method.
Generated code by thrift compiler:
class InvalidArgumentsError : public ::apache::thrift::TException {
public:
static const char* ascii_fingerprint; //..
static const uint8_t binary_fingerprint[16]; //..
InvalidArgumentsError() : parameter() {
}
virtual ~InvalidArgumentsError() throw() {}
std::string parameter;
_InvalidArgumentsError__isset __isset;
void __set_parameter(const std::string& val) {
parameter = val;
}
//...
};
If you want to stop the repetitive typing then this might be a solution.
When you want to catch your exceptions, you write something like this:
catch (...) {
handle_exception(print_message);
}
print_message is a function that does whatever you want with the message (in this case, print it):
void print_message(char const* const msg)
{
std::cout << msg;
}
handle_exception is written like this:
template<typename F>
void handle_exception(F handler)
try {
throw;
}
catch (InvalidArgumentsError const& ex) {
handler(ex.parameter.c_str());
}
catch (ServerInternalError const& ex) {
handler(ex.parameter.c_str());
}
catch (NoDataError const& ex) {
handler(ex.parameter.c_str());
}
catch (apache::thrift::TException const& ex) {
handler(ex.what());
}
catch (std::exception const& ex) {
handler(ex.what());
}
To handle a new exception you add it to the catch clauses of the handle_exception function.
Albeit this does not really answer the question literally (#Simple did a good job at this already) I would like to propose a somewhat different approach.
Given the code posted above:
exception InvalidArgumentsError {
1: string parameter
}
exception ServerInternalError {
1: string parameter
}
exception NoDataError {
1: string parameter
}
If we look at the pattern, we could - without loosing any information and without producing greater incompatibilities - change it into this:
enum ErrorCode
Success = 0, // always good to have some null value
ServerInternalError = 1
NoData = 2
InvalidArguments = 3
// add more errors here
}
exception MyServiceException {
1: string parameter
2: ErrorCode code
}
I'm fully aware that this might not fit your particular problem (e.g. if there are more exception data than just a 1:parameter). But there may be cases where that approach could be worth considering. I've used it myself quite a few times.

c++: Catch runtime_error

I am learning c++ at home and I am using the rapidxml lib.
I am using the utils provided with it to open files:
rapidxml::file<char> myfile (&filechars[0]);
I noticed that if filechars is wrong the rapidxml::file throw a runtime_error:
// Open stream
basic_ifstream<Ch> stream(filename, ios::binary);
if (!stream)
throw runtime_error(string("cannot open file ") + filename);
stream.unsetf(ios::skipws);
I think I need to write something like that:
try
{
rapidxml::file<char> GpxFile (pcharfilename);
}
catch ???
{
???
}
I made some googling, but I did not find what I need in the place of the ???.
Could somebody help me?
Thanks!
You need to add an exception declaration next to the catch statement. The type thrown is std::runtime_error.
try
{
rapidxml::file<char> GpxFile (pcharfilename);
}
catch (const runtime_error& error)
{
// your error handling code here
}
If you need to catch multiple, different kinds of exceptions, then you can tack on more than one catch statement:
try
{
rapidxml::file<char> GpxFile (pcharfilename);
}
catch (const runtime_error& error)
{
// your error handling code here
}
catch (const std::out_of_range& another_error)
{
// different error handling code
}
catch (...)
{
// if an exception is thrown that is neither a runtime_error nor
// an out_of_range, then this block will execute
}
try
{
throw std::runtime_error("Hi");
}
catch(std::runtime_error& e)
{
cout << e.what() << "\n";
}
Well, it depends on what you want to do when it happens. This is the minimum:
try
{
rapidxml::file<char> GpxFile (pcharfilename);
}
catch (...)
{
cout << "Got an exception!"
}
If you want to get at the actual exception, then you need to declare a variable to store it in inside the parentheses in place of the three dots.

c++ design question try catch

I have the following code in which dbh constructor may throw exception. The question I have is, dbh is declared inside try block. Will it be available after the catch? If yes, are there any other exceptions where the scope resolution is different than {} ? If not, what is the best design alternative?
status func(const char* field, char** value)
{
try {
dbhandler<recType> dbh(("dbName"),("table"));
}
catch (std::runtime_error &e) {
LOG_ERR << e.what() << endl ;
return false;
}
catch (...) {
LOG_ERR << "Unknown exception" << endl ;
return false;
}
rc = dbh.start("key",field, val);
return rc;
}
Will it be available after the catch?
No. It will be destroyed at the end of the block in which it is declared, just like any other local variable.
try {
dbhandler<recType> dbh(("dbName"),("table"));
} // dbh.~dbhandler<recType>() is called to destroy dbh
What is the best design alternative?
Declare dbh outside of the try block or move all the code that uses it into the try block. Which one makes the most sense depends on your specific use case.
On a somewhat related note, if you catch (...), you should either rethrow the exception or terminate the application: you have no idea what exception is being handled and in general you have no idea whether it is safe to continue executing.
According to your function code, it makes much sense to write it like that:
status func(const char* field, char** value)
{
try {
dbhandler<recType> dbh(("dbName"),("table"));
status rc = dbh.start("key",field, val);
return rc;
}
catch (std::runtime_error &e) {
LOG_ERR << e.what() << endl ;
return false;
}
catch (...) {
LOG_ERR << "Unknown exception" << endl ;
return false;
}
}

Catching all unhandled C++ exceptions?

Is there some way to catch exceptions which are otherwise unhandled (including those thrown outside the catch block)?
I'm not really concerned about all the normal cleanup stuff done with exceptions, just that I can catch it, write it to log/notify the user and exit the program, since the exceptions in these casese are generaly fatal, unrecoverable errors.
something like:
global_catch()
{
MessageBox(NULL,L"Fatal Error", L"A fatal error has occured. Sorry for any inconvience", MB_ICONERROR);
exit(-1);
}
global_catch(Exception *except)
{
MessageBox(NULL,L"Fatal Error", except->ToString(), MB_ICONERROR);
exit(-1);
}
This can be used to catch unexpected exceptions.
catch (...)
{
std::cout << "OMG! an unexpected exception has been caught" << std::endl;
}
Without a try catch block, I don't think you can catch exceptions, so structure your program so the exception thowing code is under the control of a try/catch.
Check out std::set_terminate()
Edit: Here's a full-fledged example with exception matching:
#include <iostream>
#include <exception>
#include <stdexcept>
struct FooException: std::runtime_error {
FooException(const std::string& what): std::runtime_error(what) {}
};
int main() {
std::set_terminate([]() {
try {
std::rethrow_exception(std::current_exception());
} catch (const FooException& e) {
std::cerr << "Unhandled FooException: " << e.what() << std::endl;
} catch (const std::exception& e) {
std::cerr << "Unhandled exception: " << e.what() << std::endl;
} catch (...) {
std::cerr << "Unhandled exception of unknown type" << std::endl;
}
std::abort();
});
throw FooException("Bad things have happened.");
// throw std::runtime_error("Bad things have happened.");
// throw 9001;
}
You can use SetUnhandledExceptionFilter on Windows, which will catch all unhandled SEH exceptions.
Generally this will be sufficient for all your problems as IIRC all the C++ exceptions are implemented as SEH.
Without any catch block, you won't catch any exceptions. You can have a catch(...) block in your main() (and its equivalent in each additional thread). In this catch block you can recover the exception details and you can do something about them, like logging and exit.
However, there are also downside about a general catch(...) block: the system finds that the exception has been handled by you, so it does not give any more help. On Unix/Linux, this help would constitute creating a CORE file, which you could load into the debugger and see the original location of the unexcepted exception. If you are handling it with catch(...) this information would be already lost.
On Windows, there are no CORE files, so I would suggest to have the catch(...) block. From that block, you would typically call a function to resurrect the actual exception:
std::string ResurrectException()
try {
throw;
} catch (const std::exception& e) {
return e.what();
} catch (your_custom_exception_type& e) {
return e.ToString();
} catch(...) {
return "Ünknown exception!";
}
}
int main() {
try {
// your code here
} catch(...) {
std::string message = ResurrectException();
std::cerr << "Fatal exception: " << message << "\n";
}
}
Update: This covers c++98 only.
From More Effective C++ by Meyers (pg 76), you could define a function that gets called when a function generates an exception that is not defined by its exception specification.
void convertUnexpected()
{
// You could redefine the exception here into a known exception
// throw UnexpectedException();
// ... or I suppose you could log an error and exit.
}
In your application register the function:
std::set_unexpected( convertUnexpected );
Your function convertUnexpected() will get called if a function generates an exception that is not defined by its exception specification... which means this only works if you are using exception specifications. ;(
Provided that C++11 is available, this approach may be used (see example from: http://en.cppreference.com/w/cpp/error/rethrow_exception):
#include <iostream>
#include <exception>
void onterminate() {
try {
auto unknown = std::current_exception();
if (unknown) {
std::rethrow_exception(unknown);
} else {
std::cerr << "normal termination" << std::endl;
}
} catch (const std::exception& e) { // for proper `std::` exceptions
std::cerr << "unexpected exception: " << e.what() << std::endl;
} catch (...) { // last resort for things like `throw 1;`
std::cerr << "unknown exception" << std::endl;
}
}
int main () {
std::set_terminate(onterminate); // set custom terminate handler
// code which may throw...
return 0;
}
This approach also allows you to customize console output for unhandled exceptions: to have something like this
unexpected exception: wrong input parameters
Aborted
instead of this:
terminate called after throwing an instance of 'std::logic_error'
what(): wrong input parameters
Aborted
This is what I always do in main()
int main()
{
try
{
// Do Work
}
catch(std::exception const& e)
{
Log(e.what());
// If you are feeling mad (not in main) you could rethrow!
}
catch(...)
{
Log("UNKNOWN EXCEPTION");
// If you are feeling mad (not in main) you could rethrow!
}
}
Use catch (...) in all of your exception barriers (not just the main thread). I suggest that you always rethrow (...) and redirect standard output/error to the log file, as you can't do meaningful RTTI on (...). OTOH, compiler like GCC will output a fairly detailed description about the unhandled exception: the type, the value of what() etc.