سؤال

I was arguing with a colleague about the dangers of using catch(...)

He was pointing me a possible use, rigorously implying that any catch(...) is followed by a trace/log: so as to help determining the origins of some unmanaged exceptions.

I am personnally rather skeptical about that. Do you know about any clear safe use of catch(...)

EDIT: For those interessested in the debate, my colleague has just pointed me to this question on Programmers site.

هل كانت مفيدة؟

المحلول 2

Exceptions are often overused. Almost always this overuse is accompanied by catch-all statements. This is usually a sign of a bad use and understanding of exceptions. I never recommend it. Sadly, at some (bad) place I worked in, other people enforced this policy.

نصائح أخرى

The clearest interesting safe use of catch(...) that I'm aware of is to offload code for handling various exceptions to a shared function:

void handle_error() {
    try {
        throw;
    } catch (TiresomelyPedanticException &) {
        # lah lah I don't care
        return;
    } catch (InterestingException &) {
        log_something();
        throw;
    }
    // etc. This catch chain may *or may not* need a catch(...)
    // of its own, it depends whether part of its job is to
    // deal with the "miscellaneous" case.
}

You use the function like this:

try {
    blah();
} catch(...) {
    handle_error();
}

... somewhere else ...

try {
    something_that_throws_the_same_exceptions_as_blah();
} catch (...) {
    handle_error();
}

The pattern above might turn out to be a bit of a C++03-ism, though. In C++11 it's so easy to write a capturing lambda, that the following might be more useful to callers, and there's no catch(...) in the pattern:

template <typename Func>
auto do_and_handle_error(Func f) -> decltype(f()) {
    try {
        return f();
    } // catch chain goes here
}

Use it like:

do_and_handle_error(blah);

or as would actually turn out to be necessary when blah takes arguments:

do_and_handle_error([&](void) { return blah(arg1,arg2); });

A boring use of catch(...) is to guarantee that the stack will be unwound before program termination:

int my_main() {
    RAIIClass some_object_i_want_to_get_destroyed_no_matter_what;
    some_code_that_might_throw();
    return 0;
}

int main() {
    try {
        return my_main();
    } catch (...) {
        throw;
    }
}

Without the catch, the standard leaves it either unspecified or implementation-defined whether or not some_object is destroyed if the code throws.

The following is always safe:

try
{
    some_local_stuff();
}
catch (...)
{
    clean_up_local_stuff();
    throw;
}

In other words, the catch-all catch block should only be used in conjunction with either rethrowing the exact same exception or storing exception pointer to transport the exception.

Catch blocks that make an exception go away entirely should be specific about the type of exception they handle.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top