throwing exception from constructor in C++ - c++

I have read several articles here and else where that it is OK to throw exception from constructor. However, I have noticed that it doesn't call destructor of base class or its data members if an exception is thrown from the constructor. Consider the following example:
#include <iostream>
using namespace std;
struct C
{
C() { cout << __FUNCTION__ << endl; }
~C() { cout << __FUNCTION__ << endl; }
};
struct E: public C
{
C c;
E() { cout << __FUNCTION__ << endl; throw 4; }
~E() { cout << __FUNCTION__ << endl; }
};
int main()
{
E e;
}
$ g++ test.cpp; ./a.exe
C
C
E
terminate called after throwing an instance of 'int'
Aborted (core dumped)
In this case, E's constructor throws an exception but C's destructor as a data member or as a base class is not called. Now if C's destructor performs some cleanup operation like closing files/sockets and deleting heap allocations, this can cause problems.
So my question is why and when is it OK to throw exceptions from constructors.

If you catch the error, the destructor will be run. When an uncaught exception is thrown in C++, the runtime calls std::terminate. By default, std::terminate calls std::abort which specifically does not call destructors on the way out.
With this version:
#include <iostream>
using namespace std;
struct C
{
C() { cout << __FUNCTION__ << endl; }
~C() { cout << __FUNCTION__ << endl; }
};
struct E: public C
{
C c;
E() { cout << __FUNCTION__ << endl; throw 4; }
~E() { cout << __FUNCTION__ << endl; }
};
int main()
{
try {
E e;
} catch(...) {
}
return 0;
}
I get output:
C
C
E
~C
~C

I have noticed that it doesn't call destructor of base class or its data members if an exception is thrown from the constructor
Yes, it does.
However, since you don't catch that exception in the entire program, the program is immediately terminated.
If you were to catch the exception somewhere higher up the call stack, then the destructors of base class and members would be invoked as expected.

You don't handle the "exception".
> cat test.cpp
#include <iostream>
using namespace std;
struct C
{
C() { cout << __FUNCTION__ << endl; }
~C() { cout << __FUNCTION__ << endl; }
};
struct E: public C
{
C c;
E() { cout << __FUNCTION__ << endl; throw 4; }
~E() { cout << __FUNCTION__ << endl; }
};
int main()
{
try
{
E e;
}
catch (int i)
{
std::cerr << "Handled " << i << std::endl;
}
}
Build and run..
> make test
make: `test' is up to date.
> ./test
C
C
E
~C
~C
Handled 4
>
Both Cs destructed and a perfectly normal termination.

1) E's constructor catched the exception and ran completly.
Therefore, its object is created and the distructor is
invoked.
struct C
{
C() {cout <<__FUNCTION__<< endl;}
~C() {cout <<__FUNCTION__<< endl;}
};
struct E: public C
{
C c;
E() {
try {
cout <<__FUNCTION__<< endl;
throw 4;
}
catch(int i) {
cerr<<"int "<<i<<" is catched by "<<__FUNCTION__<<endl;
}
}
~E() {cout << __FUNCTION__ << endl;}
void print(){
cout<<"obj of class E is created"<<endl;
}
};
int main()
{
try {
E e;
e.print();
}
catch(int i) {
cerr<<"int "<<i<<" catched by "<<__FUNCTION__<<" function"<<endl;
}
return 0;
}
/*
Results:
C::C
C::C
E::E
int 4 is catched by E::E
obj of class E is created
E::~E
C::~C
C::~C
*/
2) E's constructor didn’t catch the exception and ran incompletly.
In result, its object is not created. Therefore, its distructor
is not invoked.
struct C
{
C() {cout <<__FUNCTION__<< endl;}
~C() {cout <<__FUNCTION__<< endl;}
};
struct E: public C
{
C c;
E() {
try {
cout <<__FUNCTION__<< endl;
throw 4;
}
catch(float i) {
cerr<<"int "<<i<<" is catched by "<<__FUNCTION__<<endl;
}
}
~E() {cout << __FUNCTION__ << endl;}
void print(){
cout<<"obj of class E is created"<<endl;
}
};
int main()
{
try {
E e;
e.print();
}
catch(int i) {
cerr<<"int "<<i<<" catched by "<<__FUNCTION__<<" function"<<endl;
}
return 0;
}
/*
Results:
C::C
C::C
E::E
C::~C
C::~C
int 4 catched by main function
*/

Related

Does std::any_cast call destructor? How the cast works?

#include <iostream>
#include <any>
using namespace std;
class c {
public:
c() :a{ 0 } { cout << "constructor\n"; }
c(int aa) :a{ aa } { cout << "Constructor\n"; }
~c() { cout << "destructor\n"; }
int get() { return a; }
private:
int a;
};
auto main()->int
{
any a{ 5 };
cout << any_cast<int>(a) << '\n';
a.emplace<c>(3);
cout << '!' << any_cast<c>(a).get() << '\n';
//des
cout << '\n';
a.emplace<c>(9);
cout << '!' << any_cast<c>(a).get() << '\n';
//des
}
destructor called after each any_cast.
and, below code makes run-time error.
I think the cause is any_cast(C)'s work pipeline is might be like
~C() then X(C) ERROR!!C doesn't exist
any_cast really work like that?
I add blow codes and make run-time error.
class X {
public:
X() :a{ 0 } { cout << "xonstructor\n"; }
X(c& aa) :a{ aa.get() } { cout << "Xonstructor\n"; }
~X() { cout << "Xdestructor\n"; }
int get() { return a; }
private:
int a;
};
auto main()->int
{
any a{ 5 };
cout << any_cast<int>(a) << '\n';
a.emplace<c>(3);
cout << '!' << any_cast<X>(a).get() << '\n';
//runtime error after '!'
cout << '\n';
a.emplace<c>(9);
cout << '!' << any_cast<X>(a).get() << '\n';
}
You are copying a c (or X) from the one within the std::any. That copy is destroyed at the end of the expression, after having been streamed out.
any_cast does not do any conversion. It throws if you ask it for a type different to the one it stores. When you have emplaced a c and asked for an X, it throws std::bad_any_cast, because X is not c.

How to issue a c++ termination catch without a OOM killer

I am learning about exceptions from a book and try/catch and the OS should terminate the following program.
The book says, the message terminate called after throwing an instance of 'std::bad_alloc' should show up. But doesn't.
I am using Arch Linux and the program is not stopping. It runs, fills the RAM a bit linear until it doesn't (at about 90%), the processor is working a lot but no freezing and no terminating.
Is this a Windows only use case or how could I reproduce the error on a Linux/maybe Unix system?
#include <iostream>
#include <exception> //c++ exception
int main()
{
int *feld;
int loop = 1;
for(;;) //infinite loop
{
std::cout << "Loop number: " << loop << '\n';
try
{
feld = new int[10000];
loop++;
if (durchlauf == 100000) //since c++11
std::terminate();
}
catch(...)
{
std::cout << "Error, Program done.\n";
break;
}
}
return 0;
}
EDIT: I found out that my OOM killer is not working properly with swap enabled/at all. But c++ has its own termination process call
https://en.cppreference.com/w/cpp/error/terminate
It just doesn't issues an exception to print out the catch line.
Has anyone a hint to issue a catch termination?
I found the following code for you to program some terminations:
Hope that helps.
#include <iostream>
#include <stdexcept>
struct A {
int n;
A(int n = 0): n(n) { std::cout << "A(" << n << ") constructed successfully\n"; }
~A() { std::cout << "A(" << n << ") destroyed\n"; }
};
int foo()
{
throw std::runtime_error("error");
}
struct B {
A a1, a2, a3;
B() try : a1(1), a2(foo()), a3(3) {
std::cout << "B constructed successfully\n";
} catch(...) {
std::cout << "B::B() exiting with exception\n";
}
~B() { std::cout << "B destroyed\n"; }
};
struct C : A, B {
C() try {
std::cout << "C::C() completed successfully\n";
} catch(...) {
std::cout << "C::C() exiting with exception\n";
}
~C() { std::cout << "C destroyed\n"; }
};
int main () try
{
// creates the A base subobject
// creates the a1 member of B
// fails to create the a2 member of B
// unwinding destroys the a1 member of B
// unwinding destroys the A base subobject
C c;
} catch (const std::exception& e) {
std::cout << "main() failed to create C with: " << e.what();
}
Just for the sake of being helpful if someone steps into the same problem
a coded thrown exception after 100000 loops:
#include <iostream>
#include <exception> //c++ exception
int main()
{
int *feld;
int loop = 1;
for(;;) //infinite loop
{
std::cout << "Loop number: " << loop << '\n';
try
{
feld = new int[10000];
loop++;
if (loop == 1e5)
throw std::bad_alloc(); //has to be inside the try(){} scope
}
catch(...)
{
std::cout << "Error, Program done.\n";
break;
}
}
return 0;
}

Inherit from two parent class (which inherit from one base class) but some methods don't work

i have troubles with some methods after inherit.
It's hard (for me) to say where exactly problem is but i will try to expose this by example.
Minimal code:
#include <iostream>
class A
{
public:
A() {};
A(int x):val(x)
{
std::cout << "A constructor work" << std::endl;
}
int get()
{
std::cout << "Get A work" << std::endl;
return val;
}
protected:
int val;
};
class B: protected A
{
public:
B(int x) :A(x)
{
std::cout << "B constructor work" << std::endl;
test();
}
int get()
{
std::cout << "Get B work" << std::endl;
return A::get();
}
protected:
void test()
{
if (A::val == 0)
{
std::cout << "Test B work" << std::endl;
A::val = 1;
}
}
};
class C : protected A
{
public:
C() {};
C(int x) :A(x)
{
std::cout << "C constructor work" << std::endl;
test();
}
int get()
{
std::cout << "Get C work" << std::endl;
return A::get();
}
protected:
void test()
{
std::cout << "Test C work" << std::endl;
if (A::val != 0)
{
A::val += 2;
}
}
};
class D : private B, private C
{
public:
D(int x):B(x)
{
std::cout << "D constructor work" << std::endl;
C::test();
}
int get()
{
std::cout << "Get D work" << std::endl;
return B::get();
}
};
int main()
{
D d(0);
std::cout << d.get() << std::endl;
}
Output:
**A constructor work
B constructor work
Test B work
D constructor work
Test C work
Test C extra work
Get D work
Get B work
Get A work
1**
I expect val = 3 in the end, but it dont work like that.
I would be particularly grateful for your detailed reply.
Your class D contains two A objects - the one inherited by B and the one inherited by C
When you call C::test() you change the A object in C.
When you call D::get() - which calls B::get() - you inspect the value of the A object in B.
One way to get around this is by means of virtual inheritance. That is not something you want to mess with until you understand how multiple inheritance works, though.

Exception handling for class hierarchies

When I talk about exception handling for classes, I am not really sure if I understood the exceptions really well. One grey area which I can find is to handle exceptions for class hierarchies. For e.g.
#include<iostream>
class B {
public:
B() {
std::cout << "B ctor" << std::endl;
}
~B() {
std::cout << "B dtor" << std::endl;
}
};
class D : public B {
public:
D() {
std::cout << "D ctor" << std::endl;
}
~D() {
std::cout << "D dtor" << std::endl;
}
};
int main() {
try {
D d;
throw d;
} catch (D &d) {
std::cout << "Derived caught" << std::endl;
} catch (B &b) {
std::cout << "Base caught" << std::endl;
}
}
This actually prints :
B ctor
D ctor
D dtor
B dtor
Derived caught
D dtor
B dtor
D dtor
B dtor
I did not understand why and what should I do to overcome this in case it is not encouraged.

When catching an exception's parameter by value, what is the order in which the destructors are called?

In the following code, what is the order in which the destructors of b, q and e are called, and which is called before handling the exception.
(The "cout..." parts are leftover for the original question)
#include <iostream>
using namespace std;
class A {
public:
A(int arg) : m(arg) {
cout << "A::A(int) " << m << endl;
m = 2*arg;
}
virtual void f() {
cout << "A::f() " << m << endl;
}
void g() {
cout << "A::g(A) " << m << endl;
}
int m;
};
class B : public A {
public:
B(int arg) : A(arg) {
cout << "B::B(int) " << m << endl;
m = 3*arg;
}
~B() {
cout << "B::~B()" << endl;
}
void f() {
cout << "B::f(A&) " << m << endl;
}
virtual void g() {
B q(*this);
throw q;
cout << "B::g(A) " << m << endl;
}
};
int main() {
try {
B b(1);
b.g();
} catch (A e) {
cout << "Error: ";
e.f();
}
return 0;
}
If it's possible, could you explain the reason.
Thank you.
q's desctructor is called first because it is destroyed as the first part of stack unwinding (local objects in the inner most scope are destroyed first), then b's destructor is called, also as part of stack unwinding. Both are destroyed before the catch block is even entered. Stack unwinding happens before the exception handler is executed.
Bear in mind, though, that exception objects are copied so in B::g() a copy (the exception object) of q which is a copy of b is created and its lifetime extends to the end of the catch block. It is used to initialize (slicing!) e.
The destructor for the exception object itself (a copy of q) is executed immediately after e is destroyed (as the handler doesn't exit via a throw;). This ordering is specified in the standard.