1

It is said that defining a function as noexcept will let the compiler do some optimizations to boost the program and if the function needs to throw the compiler will suppress that optimization.

Here's my simple snippet:

void func() noexcept(true){
    std::vector<int> vec{2, 4, 6, 8}; // vec is a vector of 4 ints
    std::cout << vec.at(5); // throws
}

int main(){

    try{
        func();
    }
    catch(std::exception const& e){
        std::cout << e.what() << '\n';
    }
    catch(...){
        //
    }

}
  • Why I cannot catch the exception? I am sure because the noexcept exception specification. So what happens if a function is marked as noexcept but throws and how to catch its exception rather than letting the program call std::terminate() to end the program?
Itachi Uchiwa
  • 3,044
  • 12
  • 26
  • 7
    `func` has promised to never, ever throw an exception; and `std::terminate` will be called if it breaks that promise. You have to change the body of `func` to catch the exception and return an error another way. – Richard Critten Mar 08 '21 at 21:23
  • 2
    Also this information _"...and if the function needs to throw the compiler will suppress that optimization...."_ is incorrect. – Richard Critten Mar 08 '21 at 21:29
  • @RichardCritten: I've read that information from C++ primer 5th ed. "Moreover, if the compiler knows that no exceptions will be thrown, it can (sometimes) perform optimizations that must be suppressed if code might throw". – Itachi Uchiwa Mar 08 '21 at 21:35
  • Does this answer your question? [noexcept, stack unwinding and performance](https://stackoverflow.com/questions/26079903/noexcept-stack-unwinding-and-performance) – Richard Critten Mar 08 '21 at 21:38
  • 2
    And to answer your comment directly - `func` has promised to __never__ throw so _"...might throw..."_ is impossible and the optimisation (if there is one) will always happen. – Richard Critten Mar 08 '21 at 21:40
  • @RichardCritten: So it is a mistake in the book? – Itachi Uchiwa Mar 08 '21 at 21:51
  • 2
    @ItachiUchiwa no, you are just misinterpreting what it is saying. "*Moreover, if the compiler knows that no exceptions will be thrown [because `nothrow(true)` is used], it can (sometimes) perform optimizations that must be suppressed if code might throw [when `nothrow(true)` is not used]*" – Remy Lebeau Mar 08 '21 at 21:54
  • 1
    No you are misunderstanding the quote. _"... "Moreover, if the compiler knows that no exceptions will be thrown,..."_ stop here `noexcept(true)` has been specified so the compiler knowns that no exceptions can be thrown and therefore optimizations (if possible) can be performed The compiler does not look at every function called in `func` and try to determine what can throw and what can't. The writer of `func` has promised the compiler that no exception will leave `func`. – Richard Critten Mar 08 '21 at 21:54
  • @RemyLebeau: Thank you! It was really misleading. Now it is clear so those optimizations will be suppressed if code might throw means if the function is marked `noexcept(false);` right? – Itachi Uchiwa Mar 08 '21 at 22:03
  • @RichardCritten: Thank you! – Itachi Uchiwa Mar 08 '21 at 22:04

1 Answers1

2

Why I cannot catch the exception?

Because the function is noexcept. This is exactly what it means. Declaring a function noexcept is a promise that nothing will ever be thrown out of the function. As a consequence, the compiler doesn't need to generate exception handling code. If that promise is broken, then the exception cannot be handled and only reasonable way to proceed is to terminate.

So what happens if a function is marked as noexcept but throws

If an exception is thrown out of the noexcept function, then the process is terminated.

and how to catch its exception rather than letting the program call std::terminate() to end the program?

There is no way to catch an exception thrown out of a noexcept function. Your options are:

  • Accept that the process will be terminated if that happens.
  • Don't let exceptions be thrown from noexcept functions, thus avoiding the termination. Note that throwing inside is fine, as long as nothing is thrown out.
  • Don't declare functions that throw as noexcept, allowing you to handle the exception.
eerorika
  • 232,697
  • 12
  • 197
  • 326
  • But you can swallow that exception locally inside that function (handle it inside its body without letting it leave the function). – Itachi Uchiwa Mar 08 '21 at 22:07
  • 1
    @ItachiUchiwa Like I said: `Don't let exceptions be thrown from noexcept functions`. Throwing exceptions inside is fine as long as you don't throw anything out. – eerorika Mar 08 '21 at 22:08
  • OK get it Thank you – Itachi Uchiwa Mar 08 '21 at 22:15
  • Another option in some cases could be to use `std::set_terminate` near the program start, to attempt some last-ditch logging, cleanup, etc. The program will still need to terminate in the same cases, but it could be possible to do a little bit about it first. – aschepler Mar 08 '21 at 22:25