2

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;
}
Kiran
  • 5,478
  • 13
  • 56
  • 84

2 Answers2

8

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.

James McNellis
  • 348,265
  • 75
  • 913
  • 977
  • I would recommend that you use the first option here, unless the amount of code that used `dbh` is very small. You may have to use more try blocks but catching exceptions early and catching them specifically is crucial to safe coding. :) – Dennis Feb 25 '11 at 17:39
  • @Dennis: Perhaps. If you have a whole sequence of tasks that needs to complete successfully, it may be easier to handle failures at a higher level. This is a major advantage of using exceptions for error handling: you can handle errors wherever it makes the most sense to do so. – James McNellis Feb 25 '11 at 17:45
  • Got the answer. Thanks.. I was trying to see the best alternative between a simplified API and error checking – Kiran Feb 25 '11 at 18:00
  • 1
    "in general you have no idea whether it is safe to continue executing" - two possibilities - either `dbhandler` is exception-safe, or it isn't. If it is, then it's somewhat vague to `catch(...)`, but the `dbhandler` documentation might be equally vague, and our program might quite happily operate with limited functionality without handling the db. If `dbhandler` isn't at least basically exception-safe then it's not strictly *our* fault that *it* broke our program. I agree we shouldn't have to `catch(...)`, though, if only because dbhandler shouldn't throw non-`std::exception` exceptions. – Steve Jessop Feb 25 '11 at 18:17
  • I wonder what it is about exceptions that causes this fear and uncertainty - if in a C program you see `if init_dbhandler(&dbh, blah, blah) != 0 { return false; }` you might think, "hmm, this function should probably propagate errors upwards rather than returning just a yes/no answer, on the assumption that `init_dbhandler` uses errnos like everyone else", but you don't normally think "aargh! We should `abort`, the program could be in an undefined state because something failed!" ;-) – Steve Jessop Feb 25 '11 at 18:20
  • @Steve: Well, I did say "in general." In new, high quality code, you should at least have _some_ idea what exceptions might be thrown by an operation. In less well written code, perhaps you might have to take more chances. As for "fear and uncertainty," I know that mine partially comes from having worked on a system that used the evil [/EHa](http://msdn.microsoft.com/en-us/library/1deeycx5.aspx) in Visual C++, so if you used `catch (...)` the system really might be in an undefined state because you might have caught an access violation, stack overflow, or worse. – James McNellis Feb 25 '11 at 18:28
  • @Steve: That is a very good point about C-style error handling via returning status codes, though. I'm not sure what to think about that. – James McNellis Feb 25 '11 at 18:31
  • @James: all I've come up with is that people *should* document all behavior in error conditions, whether exceptions or error returns. In practice they (including me) don't always. I've seen C code where error-propagation has got out of hand to the point where you no longer know what a given non-zero return means from some functions, or even whether it being equal to an errno implies it was originally caused by that errno or by someone's custom list of error codes. Seems to be rarer though than code in exception-throwing languages where exceptions are totally undocumented. – Steve Jessop Feb 25 '11 at 18:40
2

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;
    }
}
tibur
  • 11,531
  • 2
  • 37
  • 39