Below code exits by giving error
"abort() has been called".
Is it due to destructor throwing exception? I know throwing exception from destructor results in undefined behavior but there are counter arguments also. and moreover the same program works correct in VS 2012.
#include "stdafx.h"
#include<iostream>
using namespace std;
class Txn
{
public:
Txn()
{
cout<< "in Constructor" << endl;
};
~Txn()
{
try
{
cout << "in destructor" << endl;
throw 10;
}
catch(int i)
{
cout << "in destructor exception" << endl;
throw;
}
}
};
int main()
{
try
{
Txn t;
}
catch (int i)
{
cout << "Exception" << i << endl;
}
return 0;
}
VS2017 release notes does not mention anything around exception handling changes.
So i have below questions:
Is it incorrect to throw exception in destructor from VS2017 onwards? will it always exit the program by calling abort()?
Are there any flags with which we can make it work?
Please suggest.
The issue here is all destructors by default are noexcept(true). Throwing an exception without changing the will call std::terminate immediately. If we use
class Txn
{
public:
Txn()
{
cout<< "in Constructor" << endl;
};
~Txn() noexcept(false)
{
try
{
cout << "in destructor" << endl;
throw 10;
}
catch(int i)
{
cout << "in destructor exception" << endl;
throw;
}
}
};
int main()
{
try
{
Txn t;
}
catch (int i)
{
cout << "Exception" << i << endl;
}
return 0;
}
The program runs as expected.
The reason this worked in VS2012 but not VS2017 is before C++11 a destructor could throw without you needing to specify it. With C++11 noexcept specifiers and the change that all destructors are noexcept by default causes it to break in VS2017.
Destructors are by default expected to not throw exceptions (noexcept). You can tell the compiler that this destructor is not using the default by adding a noexcept(false).
When trying that on this example, we now get a different diagnostic from the compiler - that the destructor will never, ever reach the end. It's not good for a destructor to never fully destroy the object...
To "fix" this I had to make the rethrow conditional with an if.
class Txn
{
public:
Txn()
{
cout<< "in Constructor" << endl;
};
~Txn() noexcept(false)
{
try
{
cout << "in destructor" << endl;
throw 10;
}
catch(int i)
{
cout << "in destructor exception" << endl;
if (i == 10) throw;
}
}
};
Undefined behaviour can be anything, including a call to abort(); Just avoid everything that may induce it.
Throwing from the destructor is not forbidden, but doing that inside a try/catch might result in double exception thrown.
Related
I wrote a small program, to check the difference between creating shared_ptr via new and make_shared() function in case of exceptions. I read everywhere that via make_shared() it is an exception-safe.
But the interesting thing about both these cases is that the destructor in both cases is not called after stack unwinding? Am I missed something? Thanks in advance.
#include <iostream>
#include <memory>
class Car
{
public:
Car() { cout << "Car constructor!" << endl; throw std::runtime_error("Oops"); }
~Car() { cout << "Car destructor!" << endl; }
};
void doProcessing()
{
// std::shared_ptr<Car> sp(new Car());
std::shared_ptr<Car> sp2 = std::make_shared<Car>();
}
int main()
{
try
{
doProcessing();
}
catch(...)
{
}
return 0;
}
What object?
The only object in a smart pointer here did not actually complete construction, because its constructor threw. It doesn't exist.
You don't need smart pointers to demonstrate this. Just throw from any constructor and you'll see that the destructor body is not invoked.
Just wanted to add an answer addressing "I read everywhere that via make_shared() it is an exception-safe" part of your question, the rest is already answered by Lightness Races in Orbit.
Difference between make_share and shared_ptr(new Car) can be demonstrated by below program.
class Car
{
public:
Car() { cout << "Car constructor!" << endl; throw std::runtime_error("Car oops"); }
~Car() { cout << "Car destructor!" << endl; }
};
class Bycicle
{
public:
Bycicle() { cout << "Bycicle constructor!, does not throw" << endl;}
~Bycicle() { cout << "Bycicle destructor!" << endl; }
};
void doProcessing(std::shared_ptr<Car> /*carPtr*/, std::shared_ptr<Bycicle> /*bPtr*/)
{
}
int main()
{
try
{
doProcessing(std::shared_ptr<Car>(new Car), std::shared_ptr<Bycicle>(new Bycicle));
}
catch(std::exception& ex)
{
std::cout << "Ex is " << ex.what() << std::endl;
}
return 0;
}
Until C++17, compiler is allowed to make following function calls (in the order described)
-- Call new Bycicle along with the constructor of Bycicle but NOT call ctor of shared_ptr.
-- Call the constructor of Car which throws.
In this case, as pointed out Car was never fully constructed so it won't leak. However constructor of Bycicle was fully executed and it does leak (since shared_ptr does NOT yet own the object).
Calling doProcessing(std::make_shared<Car>(), std::make_shared<Bycicle>()); guarantees that ownership of fully allocated objects is passed to the shared_ptr.
Final Note: This is not applicable since C++ 17, because C++ 17 guarantees that arguments are evaluated fully (order in which they are evaluated is still not guaranteed).
I'm trying to understand why throwing an exception from a destructor results in a program crash.
As I found many examples of two object which throw multiple exception and compiler can't handle multiple exception but in my case I only have a single exception thrown from the destructor. Why is my program still crashing?
class MyClass {
private:
string name;
public:
MyClass (string s) :name(s) {
cout << "constructor " << name << endl;
}
~MyClass() {
cout << "Destroying " << name << endl;
throw "invalid";
}
};
int main( )
{
try {
MyClass mainObj("M");
}
catch (const char *e) {
cout << "exception: " << e << endl;
cout << "Mission impossible!\n";
}
catch (...) {
cout << "exception: " << endl;
}
return 0;
}
Explanation from the MingW g++ compiler:
[P:\temp]
> g++ foo.cpp
foo.cpp: In destructor 'MyClass::~MyClass()':
foo.cpp:14:15: warning: throw will always call terminate() [-Wterminate]
throw "invalid";
^~~~~~~~~
foo.cpp:14:15: note: in C++11 destructors default to noexcept
To really let it throw you can do this:
~MyClass() noexcept(false){
Since C++11 destructors are implicitly declared as noexcept documentation
non-throwing functions are all others (those with noexcept specifier whose expression evaluates to true as well as destructors, defaulted special member functions, and deallocation functions)
emphasis is mine.
So we have a constructor that can throw an exception depending on the arguments passed to it, but we do not know how to delete the object if this occurs. Important part of the code:
try
{
GameBase *gameptr = GameBase::getGame(argc, argv);
if (gameptr == 0)
{
std::cout << "Correct usage: " << argv[PROGRAM_NAME] << " " << "TicTacToe" << std::endl;
return NO_GAME;
}
else
{
gameptr->play();
}
delete gameptr;
}
catch (error e)
{
if (e == INVALID_DIMENSION)
{
std::cout << "Win condition is larger than the length of the board." << std::endl;
return e;
}
}
catch (...)
{
std::cout << "An exception was caught (probably bad_alloc from new operator)" << std::endl;
return GENERIC_ERROR;
}
In the third line, GameBase::getGame() calls the constructor for one of the games derived from GameBase and returns a pointer to that game, and these constructors can throw exceptions. The question is, how can we then delete the (partial?) object pointed to by gameptr if this occurs? If an exception is thrown, we will exit the scope of gameptr because we leave the try block and cannot call delete gameptr.
To assess the exception safety, you need to provide more detail of the construction of the object in GameBase::getGame.
The rule is through, that if a constructor throws, the object is not created, hence the destructor is not called. Associated memory allocations are also deallocated (i.e. the memory for the object itself).
The issue then becomes, how was the memory allocated to begin with? If it was with a new GameBase(...), then there is no need to deallocate or delete the resultant pointer - the memory is deallocated by the runtime.
For clarity on what happens to the member variables that are already constructed; they are destructed on the exception of the "parent" object. Consider the sample code;
#include <iostream>
using namespace std;
struct M {
M() { cout << "M ctor" << endl; }
~M() { cout << "M dtor" << endl; }
};
struct C {
M m_;
C() { cout << "C ctor" << endl; throw exception(); }
~C() { cout << "C dtor" << endl; }
};
auto main() -> int {
try {
C c;
}
catch (exception& e) {
cout << e.what() << endl;
}
}
The output is;
M ctor
C ctor
M dtor
std::exception
If the M m_ member is to be dynamically allocated, favour a unique_ptr or a shared_ptr over a naked pointer, and allow the smart pointers to manage the object for you; as follows;
#include <iostream>
#include <memory>
using namespace std;
struct M {
M() { cout << "M ctor" << endl; }
~M() { cout << "M dtor" << endl; }
};
struct C {
unique_ptr<M> m_;
C() : m_(new M()) { cout << "C ctor" << endl; throw exception(); }
~C() { cout << "C dtor" << endl; }
};
The output here mirrors the output above.
When you write Foo* result = new Foo(), the compiler translates this to the equivalent of this code:
void* temp = operator new(sizeof(Foo)); // allocate raw memory
try {
Foo* temp2 = new (temp) Foo(); // call constructor
result = temp2;
} catch (...) {
operator delete(temp); // constructor threw, deallocate memory
throw;
}
So you don't need to worry about the allocated memory if the constructor throws. Note, however, that this does not apply to extra memory allocated within the constructor. Destructors are only called for objects whose constructor finished, so you should get all your allocations into small wrapper objects (smart pointers) immediately.
If you throw in a constructor, the object is not constructed and thus, you are responsible for the deletion of allocated resources. This goes even further! Consider this Code
int a = function(new A, new A);
It is up to the compiler in which ordering is the A allocated AND constructed. You might end up with an memory leak, if your A constructor can throw!
Edit:
Use instead
try{
auto first = std::make_unique<A>();
auto second = std::make_unique<A>();
int a = function(*first, *second);
...
I meant to get some knowledge of stack unwinding and came across this page,which demonstrates it with the example below.
#include <iostream>
using namespace std;
struct E {
const char* message;
E(const char* arg) : message(arg) { }
};
void my_terminate() {
cout << "Call to my_terminate" << endl;
};
struct A {
A() { cout << "In constructor of A" << endl; }
~A() {
cout << "In destructor of A" << endl;
throw E("Exception thrown in ~A()");
}
};
struct B {
B() { cout << "In constructor of B" << endl; }
~B() { cout << "In destructor of B" << endl; }
};
int main() {
set_terminate(my_terminate);
try {
cout << "In try block" << endl;
A a;
B b;
throw("Exception thrown in try block of main()");
}
catch (const char* e) {
cout << "Exception: " << e << endl;
}
catch (...) {
cout << "Some exception caught in main()" << endl;
}
cout << "Resume execution of main()" << endl;
}
However it got core dumped when I compiled with g++/*clang++*.The output is as follows:
In try block
In constructor of A
In constructor of B
In destructor of B
In destructor of A
Call to my_terminate
已放弃 (核心已转储) #core dump
Can anyone give me some hints?
The answer is that you are throwing an exception while you are throwing an exception.
In main(), you construct an A instance. You then throw an exception. Before it is caught, A::~A is called, which also throws an exception. Having two exceptions in flight at the same time causes terminate() (or the user supplied equivalent) to be called (which, by default, calls abort(), which drops a core. Either way, the program cannot recover.)
Aside: this is what leads to the general best practice rule where you must not throw exceptions in destructors unless you mean for it to kill your program.
set_terminate() expects the function providide to it terminate the program.
Function that takes no parameters and returns void. The function shall
not return and shall terminate the program. terminate_handler is a
function pointer type taking no parameters and returning void.
set_terminate automatically calls abort() after calling your terminate function if you don't exit in the function provided.
Simply add exit(0); in my_terminate() to avoid seeing this abort() message.
There are some articles concluding "never throw an exception from a destructor", and "std::uncaught_exception() is not useful", for example:
http://www.gotw.ca/gotw/047.htm (written by Herb Sutter)
But it seems that I am not getting the point. So I wrote a small testing example (see below).
Since everything is fine with the testing example I would very appreciate some comments regarding what might be wrong with it ?
testing results:
./main
Foo::~Foo(): caught exception - but have pending exception - ignoring
int main(int, char**): caught exception: from int Foo::bar(int)
./main 1
Foo::~Foo(): caught exception - but *no* exception is pending - rethrowing
int main(int, char**): caught exception: from Foo::~Foo()
example:
// file main.cpp
// build with e.g. "make main"
// tested successfully on Ubuntu-Karmic with g++ v4.4.1
#include <iostream>
class Foo {
public:
int bar(int i) {
if (0 == i)
throw(std::string("from ") + __PRETTY_FUNCTION__);
else
return i+1;
}
~Foo() {
bool exc_pending=std::uncaught_exception();
try {
bar(0);
} catch (const std::string &e) {
// ensure that no new exception has been created in the meantime
if (std::uncaught_exception()) exc_pending = true;
if (exc_pending) {
std::cerr << __PRETTY_FUNCTION__
<< ": caught exception - but have pending exception - ignoring"
<< std::endl;
} else {
std::cerr << __PRETTY_FUNCTION__
<< ": caught exception - but *no* exception is pending - rethrowing"
<< std::endl;
throw(std::string("from ") + __PRETTY_FUNCTION__);
}
}
}
};
int main(int argc, char** argv) {
try {
Foo f;
// will throw an exception in Foo::bar() if no arguments given. Otherwise
// an exception from Foo::~Foo() is thrown.
f.bar(argc-1);
} catch (const std::string &e) {
std::cerr << __PRETTY_FUNCTION__ << ": caught exception: " << e << std::endl;
}
return 0;
}
ADDED: In other words: despite of the warnings in some articles it works as expected - so what might be wrong with it?
Herb Sutter is referring to a different issue. He's talking about:
try
{
}
catch (...)
{
try
{
// here, std::uncaught_exception() will return true
// but it is still safe to throw an exception because
// we have opened a new try block
}
catch (...)
{
}
}
So the problem is that if std::uncaught_exception() returns true you don't know for sure whether you can safely throw an exception or not. You end up having to avoid throwing an exception when std::uncaught_exception() returns true just to be safe.
There's nothing technically wrong with your code. It's perfectly safe in that you will never accidentally terminate because you threw an exception when it was not safe to. The issue is that it also is not useful, in that it will occasionally also not throw an exception when it is safe to. Your destructor's documentation basically has to say "this might or might not throw an exception."
If it occasionally won't throw an exception, you might as well never throw an exception. That way, you're at least consistent.
Herb Sutter is talking about the situation when an object of class T is destroyed while there is an uncaught exception in an object of class U. std::uncaught_exception() would return true in the T destructor. The destructor would be unable to find out whether it's called during stack unwinding. If it is, it must not throw, otherwise it's business as usual.
The class U would have a problem using class T in the destructor. U would find itself dealing with a useless T object that would refuse to do anything risky in its destructor (that could include writing a log file or committing a transaction to a database).
Herb Sutter suggests never throwing in a destructor, which is a good idea. However, the C++17 offers another option. It introduced std::uncaught_exceptions(), which can be used to find out whether the destructor can throw. Following example shows the problem if complied in C++14 mode. If compiled in C++17 mode, it would work correctly.
#include <exception>
#include <iostream>
#include <string>
class T
{
public:
~T() noexcept(false)
{
#if __cplusplus >= 201703L
// C++17 - correct check
if (std::uncaught_exceptions() == uncaught_exceptions_)
#else
// Older C++ - incorrect check
if (!std::uncaught_exception())
#endif
{
throw (std::string{__PRETTY_FUNCTION__} + " doing real work");
}
else
{
std::cerr << __PRETTY_FUNCTION__ << " cowardly quitting\n";
}
}
private:
#if __cplusplus >= 201703L
const int uncaught_exceptions_ {std::uncaught_exceptions()};
#endif
};
class U
{
public:
~U()
{
try
{
T t;
}
catch (const std::string &e)
{
std::cerr << __PRETTY_FUNCTION__ << " caught: " << e << '\n';
}
}
};
int main()
{
try
{
U u;
throw (std::string{__PRETTY_FUNCTION__} + " threw an exception");
}
catch (const std::string &e)
{
std::cerr << __PRETTY_FUNCTION__ << " caught: " << e << '\n';
}
return 0;
}