16

Please tell me how to use try/catch properly with boost::exception.

This is one of examples

void Settings::init(const std::string &filename) { using boost::property_tree::ptree; try { read_xml(filename, pt); } catch(boost::exception const& ex) { LOG_FATAL("Can't init settings. %s", /* here is the question */); } } 

Do I need catch std::exception too? I can't let my application fail, so I just need to log everything.

UPD: I also can't understand now to retrive information for logging from exception???

7
  • 2
    Yes, I would add std::exception too, right after boost::exception. I would also add catch (...) Commented Nov 15, 2011 at 12:51
  • 9
    If an exception is thrown because an error occurred, then simply catching the exception does not eliminate the error. Your application still fails, you've just made it harder to see what's going on. So only catch exceptions if you can know what they indicate, and can meaningfully handle them Commented Nov 15, 2011 at 12:53
  • 1
    @jalf The above code did not simply swallow the exception. There is some logging at least. Commented Nov 15, 2011 at 12:55
  • 1
    Guys =) this is not so crucial now. you'd better tell me about UPD Commented Nov 15, 2011 at 13:02
  • 1
    UPD? What's UPD? And I think in a question about how to properly catch exceptions, discussing how exceptions should be caught us pretty crucial. ;) Commented Nov 15, 2011 at 13:46

5 Answers 5

14

std::exception has a member function called what() that returns a const char* that might explain what happened. If you want to log it (guessing that LOG_FATAL wraps printf somehow) you can do:

catch(std::exception const& ex) { LOG_FATAL("Can't init settings. %s", ex.what()); } 

For boost::exception though you can use boost::get_error_info to find out more about it.

Sign up to request clarification or add additional context in comments.

5 Comments

Although to access what() from a boost::exception, you'll need to either catch, or dynamic_cast to, std::exception.
Unless I'm mistaken, boost::exception doesn't inherit from std::exception, so your example that calls .what() on it is invalid. Also, I believe std::exception usually returns a const char* rather than a std::string
@obmarg You're mistaken. catch(boost::exception const& e){ cout << dynamic_cast<std::exception const&>(e).what(); } compiles and works perfectly.
@Qix I don't do enough C++ these days to investigate, but certainly looks like booost::exception doesn't inherit from std::exception: boost.org/doc/libs/1_55_0/libs/exception/doc/…
@Qix Ah, of course. Shame it doesn't seem to be documented obviously anywhere (though to be fair I'm not looking very hard)
10

probably WAY too late in answering... but

 <...snip...> catch (const boost::exception& e) { std::string diag = diagnostic_information(e); // display your error message here, then do whatever you need to, e.g. LOG_FATAL("Can't init settings. %s", diag); } <...snip...> 

Comments

5

As with any C++, the following universal rule applies:

Catch all exceptions that can possibly be thrown, and only if you can respond to them meaningfully.

You can catch all other exceptions (...) as well and create a log message or something like that, but then you have to rethrow them (throw;). If there's nothing you can do in your code other than abort some operation, then you don't need to handle the exception. Let it bubble up to a place where it can be used meaningfully.

In your code, you will have to allow at least for memory allocation errors (std::bad_alloc), so you could check for those, if that makes sense. But again, if you don't know what you're catching, there's not much you can do with what you catch.

Saying your "program cannot fail" can only mean so much. Ultimately, if you have an allocation error in a top-level data structure, there's nothing you can do. The best scenario I can imagine is if your main function processes some data in a loop; in that case, you can put a universal try block around the loop, and in case of an exception you just move on to the next round. But I would count that as an instance of being able to "handle an exception meaningfully", so that's just a special case of the above. In general, while you may want to wrap your entire main function in a try block, you'll just have to accept that in the ultimate catch-all case you don't have much of a choice but to abort the program.

Comments

1

That depends on the code that you're running in the try block. If the code in read_xml could throw a std::exception then you would be better to catch std::exception as well. If you're unsure, then it can't really hurt to catch both of them.

Comments

0

You should catch only special exception types if you really want to do something related to that type. Otherwise just use std::exception. If you're code could throw something different, than catch ... instead or after std::exception.

If you want to handle multiple (special) exception types than you need to handle the most explicit first.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.