Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reusing exception handling code in C++

I have these two functions, with duplicated exception treatment, which has the sole purpose of displaying an error message:

void func1() noexcept {
  try {
    do_task();
    do_another_task();
  } catch (const std::out_of_range& e) {
    show_msg("Out of range error", e.what());
  } catch (const std::logic_error& e) {
    show_msg("Logic error", e.what());
  } catch (const std::system_error& e) {
    show_msg("System error", e.what());
  } catch (const std::runtime_error& e) {
    show_msg("Runtime error", e.what());
  } catch (const std::exception& e) {
    show_msg("Generic error", e.what());
  }
}

void func2() noexcept {
  try {
    do_something();
    do_something_else();
    do_even_more();
  } catch (const std::out_of_range& e) {
    show_msg("Out of range error", e.what());
  } catch (const std::logic_error& e) {
    show_msg("Logic error", e.what());
  } catch (const std::system_error& e) {
    show_msg("System error", e.what());
  } catch (const std::runtime_error& e) {
    show_msg("Runtime error", e.what());
  } catch (const std::exception& e) {
    show_msg("Generic error", e.what());
  }
}

I could just handle std::exception and show a single generic message, but I want to be more specific, that's why I'm catching all possible exceptions.

I want to reuse this exception treatment code. I thought about this:

void run_treated(std::function<void()> func) noexcept {
  try {
    func();
  } catch // ... all the catches go here
}

void func1() noexcept {
  run_treated([]()->void {
    do_task();
    do_another_task();
  });
}

void func2() noexcept {
  do_something();
  do_something_else();
  do_even_more();
}
  1. Is this a good approach?
  2. If so, run_treated will be called a lot. Should I be concerned about performance?
  3. Any other approaches?
like image 577
rodrigocfd Avatar asked Dec 30 '17 17:12

rodrigocfd


People also ask

What are the 2 ways I can handle exception?

Java provides two different options to handle an exception. You can either use the try-catch-finally approach to handle all kinds of exceptions. Or you can use the try-with-resource approach which allows an easier cleanup process for resources.

Can we use exception handling in C?

The C programming language does not support exception handling nor error handling. It is an additional feature offered by C. In spite of the absence of this feature, there are certain ways to implement error handling in C. Generally, in case of an error, most of the functions either return a null value or -1.

How many methods are there to handle an exception in C?

There are two different methods or functions in C, which are used to display the error message instead of just displaying the errno as we did it in the above program.

What is exceptions handling with example?

Example: Exception handling using try...In the example, we are trying to divide a number by 0 . Here, this code generates an exception. To handle the exception, we have put the code, 5 / 0 inside the try block. Now when an exception occurs, the rest of the code inside the try block is skipped.


1 Answers

There's the option of using a Lippincott Function to centralize the exception handling logic. Consider this:

void Lippincott () noexcept {
  try {
    throw;
  } catch (const std::out_of_range& e) {
    show_msg("Out of range error", e.what());
  } catch (const std::logic_error& e) {
    show_msg("Logic error", e.what());
  } catch (const std::system_error& e) {
    show_msg("System error", e.what());
  } catch (const std::runtime_error& e) {
    show_msg("Runtime error", e.what());
  } catch (const std::exception& e) {
    show_msg("Generic error", e.what());
  }
}

void func1() noexcept {
  try {
    do_task();
    do_another_task();
  } catch (...) {
    Lippincott();
  }
}

void func2() noexcept {
  try {
    do_something();
    do_something_else();
    do_even_more();
  } catch (...) {
    Lippincott();
  }
}

How does it work? When you enter the handler in func1 or func2 there is a "current exception" being processed. The body of Lippincott starts a new try..catch block and re-throws it. Then it catches the appropriate exceptions and handles them accordingly in a centralized manner.

You should also note that your exception handling logic isn't really noexcept. There could theoretically be exceptions not covered by your list. In which case there are several places for std::terminate to be called, depending on how you mark things noexcept

like image 167
StoryTeller - Unslander Monica Avatar answered Oct 13 '22 18:10

StoryTeller - Unslander Monica