Tony Johansson said:
Hello!
When you allocate object dynamically which mean on the heap I find that a
problem when using exception.
What is the prefer method to handle this kind of problem.
There is no problem, its your responsability to catch the generated
exception at the level of your choice (a failed new throws a std::bad_alloc
exception). Its also your responsability to write code that doesn't generate
memory leaks so as not to find yourself in a situation where new allocations
fail. The same goes for virtual destructors in the case inheritence is
involved (a failed allocation needs to invoke the base class d~tors).
The problem, in fact, is understanding what happens when an exception is
indeed thrown. Not catching the exception *unwinds* the present scope off
the call stack and passes the exception object up to next level. If next
scope level doesn't handle the exception, that scope is unwound and the
original exception object is passed up again. This process continues until
either the exception object is caught or an unexpected exception handler
catches it.
To explain the exception-object passing unwind mechanism, consider a class N
that throws a std::bad_alloc exception in its ctor when its member is set to
2. I'm artificially throwing a new allocation failure when N *p_n2 = new
N(2) is invoked.
Note how the last 2 objects don't get constructed and therefore never get
destroyed. Throwing the std::bad_alloc exception object mimics what happens
when the allocation actually fails at runtime.
#include <iostream>
#include <stdexcept>
class N
{
int n;
public:
N(int nn) : n(nn)
{
if (2 == n) // testing std::bad_alloc exception
{
std::cout << "ctor unwind !!!\n";
throw std::bad_alloc("std::bad_alloc exception object\n");
}
std::cout << "N ctor invoked\n";
}
~N()
{
std::cout << "N d~tor invoked\n";
}
}; // class N
int main(int argc, char* argv[])
{
N *p_n0 = 0;
N *p_n1 = 0;
N *p_n2 = 0;
N *p_n3 = 0;
try
{
p_n0 = new N(0);
p_n1 = new N(1);
p_n2 = new N(2); // will throw
p_n3 = new N(3);
}
catch(const std::bad_alloc& e)
{
std::cout << "Error: " << e.what();
}
if (0 != p_n0)
delete p_n0;
if (0 != p_n1)
delete p_n1;
if (0 != p_n2)
delete p_n2;
if (0 != p_n3)
delete p_n3;
return 0;
}
/*
N ctor invoked
N ctor invoked
ctor unwind !!!
Error: std::bad_alloc exception object
N d~tor invoked
N d~tor invoked
*/
Note how the third object (*p_n2) is never allocated and the fouth
allocation (*p_n3) is never attempted.
Now, what happens if i don't wrap the new allocations in main() in a
try-catch block? Test it.