Bernard
Bernard

Reputation: 5666

Is is possible in C++ to throw nothing?

Under exceptional circumstances, I want my program to stop processing, output an error to std::cerr, clean up, and exit.

However, calling exit() will not call all the destructors of any objects that have been constructed. I would like to have the destructors called nicely, so I wrapped all the code in a try-catch block, something like this:

int main(int argc, char** argv){
    try {
        bool something_is_not_right = false;
        /* lots of variables declared here */
        /* some code that might set something_is_not_right to true goes here */
        if(something_is_not_right){
            std::cerr << "something is not right!!!" << std::endl;
            throw '\0';  // dummy unused variable for throwing.
        }
    }
    catch (...) {}
    return 0;
}

In this way, I get guaranteed destruction of all my variables. But I can't seem to find a way to get C++ to throw nothing. throw; has a special meaning in C++; it isn't throwing nothing.

Is there a way to throw nothing?

Upvotes: 6

Views: 4133

Answers (5)

Pete Becker
Pete Becker

Reputation: 76285

In order to ensure full cleanup you have to throw an exception and catch it somewhere. Implementations are not required to clean up stack objects when an exception is thrown but not caught. The requirement (in [except.handle]/9) when an exception is thrown but not caught is that the program calls std::terminate(), and it's implementation-defined whether stack objects are cleaned up.

Upvotes: 2

luk32
luk32

Reputation: 16070

Well you "can" but it doesn't throw nothing. It terminates.

5.17 Throwing an exception:

  1. Evaluating a throw-expression with an operand throws an exception (15.1)
  2. A throw-expression with no operand rethrows the currently handled exception (15.3).
  3. If no exception is presently being handled, evaluating a throw-expression with no operand calls std::terminate()

This is valid:

int main () {
  throw;
  return 0;
}

Source used: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4296.pdf

But it won't cleanup anything. std::terminate is used when the cleanups fail.

Otherwise you have to use operand, and then this section becomes relevant:

15.1 Throwing an exception [except.throw]

  1. Throwing an exception copy-initializes (8.5, 12.8) a temporary object, called the exception object. The temporary is an lvalue and is used to initialize the variable declared in the matching handler (15.3).

So you have to pass something that is able to be initialized, which by definition cannot be nothing.

Upvotes: 3

Henri Menke
Henri Menke

Reputation: 10939

This is not a direct answer to your question, but a personal recommendation.

You might want to take a look at the predefined exceptions of stdexcept which cover almost any exceptional behaviour that occurs in a program. In your case I would throw a std::runtime_error. Also, only catch what you expect to be thrown and not catch 'em all. If you really want to catch everything, then catch std::exception (the base class of all standard exceptions).

In my opinion handling unknown exceptions doesn't really make sense and the only logical consequence is to just abort execution.

#include <iostream>
#include <stdexcept>

int main()
{
  try
  {
    bool something_is_not_right = true;
    if ( something_is_not_right )
      throw std::runtime_error("something is not right!!!");
  }
  catch (std::runtime_error& e)
  {
    std::cerr << e.what() << '\n';
    throw;
  }
}

Upvotes: 8

nvoigt
nvoigt

Reputation: 77304

No

It's not possible to throw nothing. You need to throw something. While you may have seen people use the throw keyword without anything, this just means they are re-throwing the currently handled exception.

Upvotes: 12

Neil
Neil

Reputation: 11889

How do you know that the reason for the catch is your error or something else (out of memory is always a good one). If you detect an error, then you should create and throw the reason for that error in a custom exception. Then in main, you can tell the difference between your detected error and something you didn't expect. It's just good practice.

Upvotes: 3

Related Questions