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;
}
}
Related
<C++>In exception handling, do you need to know what exception and where an exception is going to occur? Can you make a code which will print and notify us that an exception occurred somewhere in the program. I mean I have a program in which I don't know if an exception will occur or not, if one was to occur, then it will print to notify us.
Exception handling is something you should design for, and in fact it works very well together with RAII (https://en.cppreference.com/w/cpp/language/raii).
(Notr On embedded platforms using exceptions, is not so popular because of some runtime overhead). What I personally like about exceptions is that it separates error handling from the normal program flow (there will be hardly any if then else checks when done right)
// Exception handling should be part of your overal design.And many standard library functions can throw exceptions, It is always up to you where you handle them.
#include <iostream>
#include <string>
#include <stdexcept>
int get_int_with_local_exception_handling()
{
do
{
try
{
std::cout << "Input an integer (local exception handling, enter a text for exception): ";
std::string input;
std::cin >> input;
// stoi is a function that can throw exceptions
// look at the documentation https://en.cppreference.com/w/cpp/string/basic_string/stol
// and look for exceptions.
//
int value = std::stoi(input);
// if input was ok, no exception was thrown so we can return the value to the client.
return value;
}
// catch by const reference, it avoids copies of the exception
// and makes sure you cannot change the content
catch (const std::invalid_argument& e)
{
// std::exceptions always have a what function with readable info
std::cout << "handling std::invalid_argument, " << e.what() << "\n";
}
catch (const std::out_of_range& e)
{
std::cout << "handling std::out_of_range, " << e.what() << "\n";
}
} while (true);
}
int get_int_no_exception_handling()
{
std::cout << "Input an integer (without exception handling, enter a text for exception): ";
std::string input;
std::cin >> input;
int value = std::stoi(input);
return value;
}
int main()
{
try
{
// this function shows you can handle exceptions locally
// to keep program running
auto value1 = get_int_with_local_exception_handling();
std::cout << "your for input was : " << value1 << "\n";
// this function shows that exceptions can be thrown without
// catching, but then the end up on the next exception handler
// on the stack, which in this case is the one in main
auto value2 = get_int_no_exception_handling();
std::cout << "your input was : " << value1 << "\n";
return 0;
}
catch (const std::exception& e)
{
std::cout << "Unhandled exception caught, program terminating : " << e.what() << "\n";
return -1;
}
catch (...)
{
std::cout << "Unknown, and unhandled exception caught, program terminating\n";
}
}
Yes and no.
No, because any exception thrown via throw some_exception; can be catched via catch(...).
Yes, because catch(...) is not very useful. You only know that there was an excpetion but not more.
Typically exceptions carry information on the cause that you want to use in the catch. Only as a last resort or when you need to make abolutely sure not to miss any excpetion you should use catch(...):
try {
might_throw_unknown_exceptions();
} catch(std::exception& err) {
std::cout << "there was a runtime error: " << err.what();
} catch(...) {
std::cout << "an unknown excpetion was thrown.";
}
The C++ standard library uses inheritance only sparingly. Exceptions is only place where it is used extensively: All standard exceptions inherit from std::exception and it is good practice to inherit also custom exceptions from it.
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).
I've project which the main look like that
Object a;
if (! a.initialize(x, y, z))
return EXIT_FAILURE;
// 100 lines using a
a.finalize();
I trying to change this part of code and using RAII idiome.
So, I delete initialize function and finalize and move the code in the constructor and destructor.
In order to catch initialize() error, I throw an exception in the constructor if something fail.
So now, my code goes like this :
try
{
Object a(x, y, z);
// 100 lines using a
} catch (my_exception&)
{
return EXIT_FAILURE;
}
the think that bother is the 100 lines of code. My try is too long for just one error. And I've multiple object like a.
so before my code was linear :
Object a;
if (! a.initialize(x, y, z))
return EXIT_FAILURE;
Object b;
Object c;
if (!b.initialize() || !c.initialize())
return EXIT_FAILURE;
a.finalize();
Now it looks ugly, difficult to read :
try
{
Object a(x, y, z);
try
{
Object b;
try
{
Object c;
}
catch (my_exception_c&)
{
return EXIT_FAILURE;
}
}
catch (my_exception_b&)
{
return EXIT_FAILURE;
}
} catch (my_exception&)
{
return EXIT_FAILURE;
}
How to do to use RAII and keep a code clear ?
In general, create a try block at the level at which you want to handle the exception. In this case, you just need a top-level block to clean up after any exception:
try {
Object a(x, y, z);
Object b;
Object c;
// code using these
} catch (...) {
// end the program if any exception hasn't been handled
return EXIT_FAILURE;
}
Now it's not "too long for one error"; it's the right length for any error which might occur.
It would be a good idea to restrict yourself to exceptions derived from std::exception; then you could give some potentially useful information in the case that it's not handled:
catch (std::exception const & ex) {
std::cerr << "ERROR: " << ex.what() << std::endl;
return EXIT_FAILURE;
}
You only need one catch like this:
try
{
Object a;
Object b;
//100 lines of code
}
catch(ExeptionA& exa)
{
cerr << "error a" << endl;
}
catch(ExeptionB& exa)
{
cerr << "error B" << endl;
}
catch(...){
cerr << "some other error" << endl;
}
(the '...' literally means '...')
This way, you'll catch all exeptions from ObjectA and ObjectB etc. in the same catch. So if you make a custom exception, it might be good to add some info in there where it came from.
You can always have another function like "IsValid()" that you check after the constructor is called instead of throwing an exception. You keep the benefits of RAII (exception safety, protection against initialization/destruction errors, ...) but you will be able to keep your code in the same format as before.
It's not as clean and safe in terms of C++ good practices, because the user can forget to check if it is valid, but the option is there.
I have this code:
printf("hello\n");
try
{
for ( unsigned i = 0; i < par.size(); i++ )
rep.delete_rev(par[i]);
}
catch(TriedToDeleteRoot e)
{
printf("catched 1 !\n");
}
catch(...) {
printf("catched sth else !\n");
}
printf("hahaha\n");
and this is what i have on output:
hello
terminate called after throwing an instance of 'TriedToDeleteRoot'
what(): Tried to delete root
why? TriedToDeleteRoot inherits from std::exception, and I don't have any idea what's wrong. Thanks.
EDIT:
this is how I throw an exception:
throw TriedToDeleteRoot();
My guess is the copy constructor for TriedToDeleteRoot is failing.
I suggest (as always) catching by const reference:
try
{
for ( unsigned i = 0; i < par.size(); i++ )
rep.delete_rev(par[i]);
}
catch(const TriedToDeleteRoot& e)
{
printf("caught 1 !\n");
}
or in the general case:
catch(const std::exception& e)
{
std::cerr << "exception: " << e.what() << std::endl;
}
You're observing that std::terminate is being called even though you have a try/catch that you expect to match the exception that's being thrown.
One reason this might happen is if you've managed to throw an exception whilst a previous exception is being handled. You can observe this with:
#include <iostream>
int main() {
try {
struct test {
~test() { throw 0; }
} test;
throw 0;
}
catch (...) {
std::cout << "Caught something" << std::endl;
}
}
On my system this calls abort() and prints:
terminate called after throwing an instance of 'int'
Notice that the catch(...) never gets hit because of this.
This simple example illustrates the easiest way to accidentally make that happen - throwing from within a destructor. My best guess from what you've shown is that this is what's happening. A debugger ought to confirm this for you though.
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.