Reputation: 3020
I have this program where the ctor of derived class throws a exception. The program is just an example program where I am just trying to understand the concept of exception handling.
class A{
public:
A() {}
~A(){std::cout << "DTOR called - A!!" << std::endl;}
};
class B : public A
{
public:
B():A()
{
try
{
init();
}
catch(...)
{
std::cout << "Inside catch block in B's Ctor!!" << std::endl;
throw this;
}
}
void init() { throw 0; }
~B() {std::cout << "DTOR called - B!!" << std::endl; }
};
int main()
{
try{
B *b = new B;
std::cout << "Äfter B's ctor called in try block!!" << std::endl;
delete b;
std::cout << "Äfter B's dtor called in try block!!" << std::endl;
}
catch(B* b)
{
delete b;
b = NULL;
std::cout << "Exception Occurred in B!!" << std::endl;
}
catch(A* a)
{
delete a;
a = NULL;
std::cout << "Exception Occurred in A!!" << std::endl;
}
catch(...)
{
std::cout << "Exception Occured!!" << std::endl;
}
return EXIT_SUCCESS;
}
The expected output is that it should enters catch block of B and first B's dtor should be called and then A's dtor. But the output of above program is:
Inside catch block in B's Ctor!!
DTOR called - A!!
DTOR called - B!!
DTOR called - A!!
Exception Occurred in B!!
My question here is why the dtor of class A called twice when it only enters the catch block for class B and calls the dtor of class B only?? Also please do tell if I am making some mistake here. Any help is appreciated
Edit:
class B : public A
{
public:
B():A()
{
try
{
szName = new char[100];
init();
}
catch(...)
{
std::cout << "Inside catch block in B's Ctor!!" << std::endl;
throw this;
}
}
void init() { throw 0; }
~B()
{
delete szName;
std::cout << "DTOR called - B!!" << std::endl;
}
char *szName;
};
Here I have created a char pointer in class B. Allocated memory in try block in Ctor before exception is being thrown. Now in this case will there be a memory leak if i do not catch exception for class B ??
Upvotes: 2
Views: 127
Reputation: 2983
1)B *b = new B;
Completed of construction of class A
construction of class B is incomplete
2) throw this;
It will release class A portion, So ~A() gets called, ~B() does not gets called as it's construction is incomplete
3)Control goes to catch(B* b)
delete b;
called ~B then ~A
Upvotes: 0
Reputation: 5299
The reason that ~A()
is called twice is because inside the body of B()
, A()
is fully initialized, so when an exception occurs, ~A()
will be called automatically, while B()
itself is not fully initialized yet, so ~B()
won't be called, and you need not and shouldn't delete the pointer if the constructor throws, C++ will call delete
for you in that case. See LIVE DEMO.
Upvotes: 2
Reputation: 254431
Don't throw this
: by the time the exception is caught, the failed object no longer exists. It has already been cleaned up, destructors called for its members and base classes, and its memory deallocated automatically by the exception handling mechanism. Trying to delete it a second time is an error.
Just throw a normal exception type (preferably a subtype of std::exception
) as you would from any other function.
Upvotes: 3
Reputation: 2182
Why are you throwing "this" in your catch block? You already barfed whilst trying to make "this", so how can you throw it? Try throwing the thing you caught, or something else, like "Oops".
Upvotes: 3