Reputation: 185
#include <iostream>
using namespace std;
struct A
{
virtual ~A() { cout << 0 << endl;};
};
struct B : A
{
int abc;
~B(){ cout << 3;}
};
int main()
{
A* ptr2 = new B[2];
delete [] ptr2;
}
The above programs generates a run time error known as a seg fault. If I remove the abc variable from struct B, everything works great. Can anyone explain this behavior?
Upvotes: -3
Views: 84
Reputation: 490128
This is a fairly common problem (or at least once was).
A pointer or reference to base can refer to an object of derived.
But a pointer or reference to base cannot reliably refer to an array of derived. If sizeof(derived) == sizeof(base)
it'll often at least appear to work, but it's still wrong. And when their sizes differ, the problems will usually be quite visible.
The official, by-the-standard answer is just "don't do that."
Unofficialy the problem is that delete [] ptr2;
doesn't know the size of the objects in the array ptr2
is referring to. Since ptr2
is a pointer to base, it tries to traverse the array as if it were an array of base objects. But when sizeof(derived) != sizeof(base)
, that doesn't work--it creates an offset into the array were the second object of the base type object would be, but since the array actually contains derived objects, that's (probably) somewhere in the middle of the first object instead of the beginning of the second object. Attempting to destroy that gives undefined behavior.
If you really need to do something like this, you can create an array of pointers to base, and initialize each of those pointers to refer to a derived object.
A ** ptr2 = new A*[2];
A[0] = new B;
A[1] = new B;
// ...
delete A[0];
delete A[1];
delete [] A;
Boost ptr_vector
can help deal with the mechanics of this, in case you care;
Upvotes: 2