Exception Handling Code Please explain it
Please see the following code and its output - please explain me the code
void abc(int);
class A
{
public:
A()
{
cout<<"Constructor Called";
}
~A()
{
cout<<"Destructor called";
}
};
int main()
{
try
{
abc(-1);
}
catch(int p)
{
cout<<p<<endl;
}
return 0;
}
void abc(int p)
{
A * Aptr = new A[2];
if(p<0)
throw p;
}
Output:
Constructor Called
Constructor Called
-1
can anyone explain why is the destructor not being called as in the case of normal stack u开发者_如何学Gonwinding
This pointer:
A * Aptr = new A[2];
is a raw pointer. When it goes out of scope only the pointer itself is destroyed - nothing is done to the array it points to. So the array is not delete[]
'ed and the destructors are not called. It's a typical example of a memory leak.
There're three typical solutions to the problem:
- allocate the array itself on stack
- use
std::vector
- use a smart pointer (not
std::auto_ptr
- it is not suitable for using with arrays.
The destructor is not called because the objects you allocate are never deleted. You would get the same output if you removed the throw
.
If, on the other hand, you changed your function into this:
void abc(int p)
{
A A_array[2];
if (p<0)
throw p;
}
You would see that the destructor was called.
As mentioned elsewhere, C++ pointers do NOT delete the memory they point to when going out of scope. You have a few options:
The hard way - try and do the memory management yourself. This way lies memory leaks and buffer overflows. Try not to do this.
void abc(int p) { A * Aptr = new A[2]; if(p<0) { delete [] Aptr; throw p; } delete [] Aptr; }
Put the array on the stack and let the normal stack unwinding handle it:
void abc(int p) { A Aptr[2]; if (p<0) throw p; }
Instead of using a raw pointer to point to the newly allocated array, hold onto it using a smart pointer class like
scoped_array
orshared_array
, or some other RAII class:void abc(int p) { boost::scoped_array<A> Aptr (new A[2]); if(p<0) throw p; } }
2 and 3 are really the only safe options in C++ code that uses exceptions - if you use raw pointers and manual memory management, you WILL end up with memory leaks sooner or later. No matter how careful you are, exception safe code pretty much requires RAII.
In addition to the suggestions concerning boost::shared_array
and boost::scoped_array
you could also just use std::vector:
std::vector<A> array( 2 );
if( p < 0 )
throw p;
Note that your types should be copyable if you go this route, however, as std::vector will copy them around during insert or when internally resizing, et cetera.
Could it be because you are not calling delete
on your A
class? If you don't delete a dynamically allocated class the desnstructor is not called.
because you allocated on the heap. What gets freed are the variables holding the pointer to the array of objects. Not the objects themselves.
Aptr is a heap-allocated variable, not a stack variable. You need to explicitly delete it for the destructor to be called (and to free the memory).
If you would instead do this:
A a[2];
and not
A *Aptr = new A[2];
you'd get the destructor called. Anything you allocate dynamically you will have to deallocate yourself.
You created the object on the heap. The destructor will be callen when you delete the object.
If you don't create the object on the heap, the destructor will be called as you expected.
精彩评论