Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Destructor that calls a function that can throw exception in C++

I know that I shouldn't throw exceptions from a destructor.

If my destructor calls a function that can throw an exception, is it OK if I catch it in the destructor and don't throw it further? Or can it cause abort anyway and I shouldn't call such functions from a destructor at all?

like image 831
Gal Goldman Avatar asked Jul 27 '09 13:07

Gal Goldman


People also ask

Can a destructor throw an exception?

In this noncompliant code example, the class destructor does not meet the implicit noexcept guarantee because it may throw an exception even if it was called as the result of an exception being thrown. Consequently, it is declared as noexcept(false) but still can trigger undefined behavior.

Can a destructor call a function?

Destructors can freely call class member functions and access class member data. There are two restrictions on the use of destructors: You cannot take its address. Derived classes do not inherit the destructor of their base class.

What happens if a destructor throws an exception C++?

When an exception is thrown, destructors of the objects (whose scope ends with the try block) are automatically called before the catch block gets executed. That is why the above program prints “Destructing an object of Test” before “Caught 10“.

Can we through exception from deconstructor?

The C++ rule is that you must never throw an exception from a destructor that is being called during the "stack unwinding" process of another exception. For example, if someone says throw Foo(), the stack will be unwound so all the stack frames between the throw Foo() and the } catch (Foo e) { will get popped.


3 Answers

Yes, that's legal. An exception must not escape from the destructor, but whatever happens inside the destructor, or in functions it calls, is up to you.

(Technically, an exception can escape from a destructor call as well. If that happens during stack unwinding because another exception was thrown, std::terminate is called. So it is well-defined by the standard, but it's a really bad idea.)

like image 151
jalf Avatar answered Sep 22 '22 00:09

jalf


Yes.

Look at the std::fstream class in the standard library for an example.

  • close() could potentially throw an exception.
  • The destroctor can call close() but the destructor does not throw (it will swallow any exceptions).

The concept is that if the destructor calls any methods that can throw then these methods should be public. Thus if the user of your object wants to check for exceptions they can use the public methods and handle the exception. If they do not care about the exception then just let the destructor handle the problem.

Going back to the std::fstream example.

{
    std::fstream   text("Plop");
    // Load Text.

    // I don't care if the close fails.
    // So let the destructor handle it and discard exceptions
}



{
    // If this fails to write I should at least warn the user.
    // So in this case I will explicitly try and close it.
    try
    {
        std::ofstram    password("/etc/password");
        // Update the password file.

        password.close();
    }
    catch(...)
    {
          Message.ShowDialog("You failed to update the Password File");
    }
}
like image 36
Martin York Avatar answered Sep 20 '22 00:09

Martin York


You can find some examples here: https://software.intel.com/sites/products/documentation/doclib/iss/2013/sa-ptr/sa-ptr_win_lin/GUID-D2983B74-74E9-4868-90E0-D65A80F8F69F.htm

If an exception leaves destructor during stack unwinding of another exception being propagated, then std::terminate() is called.

When no stack unwinding is in progress, an exception can leave destructor without std::terminate() getting called. However, for objects allocated on heap this will result in memory leak because "operator delete" will not be called for the object who throws exception out of its destructor. Surprisingly, the destructor of base class still gets called in this case: What happens to base class destructor if a derived class destructor throws an exception

If the exception is catched inside the destructor (so that the exception does not leave the destructor), then no problem even if stack unwinding of another exception is in progress. This case is described more deeply here: http://bin-login.name/ftp/pub/docs/programming_languages/cpp/cffective_cpp/MEC/MI11_FR.HTM

like image 38
Serge Rogatch Avatar answered Sep 21 '22 00:09

Serge Rogatch