开发者

Virtual dtor segmentation fault

I've got the开发者_Go百科 following code in C++:

#include <iostream> 

class Number 
{ 
public: 
    virtual void foo(){std::cout << "Number foo\n";};
    Number (){ std::cout << "Number ctor" << std::endl;} 
    virtual ~Number(){ std::cout << "Number dtor" << std::endl;} 
}; 


class Complex : public Number 
{ 
public:
    virtual void foo(){std::cout << "Complex foo\n";};
    Complex (double r=0, double i=0) : _r (r), _i (i)
    { std::cout << "Complex ctor" << std::endl; };
    virtual ~Complex(){ std::cout << "Complex dtor" << std::endl;}
private: 
    double _r,_i;
};


int main()
{
    Number *numArr = new Complex [2];
    delete [] numArr;
    return 0; 
}

When the destructors are declared as virtual, the application is quitting with segmentation fault. When it is not declared as virtual, than the Number class destructors are invoked (which is obvious...). But, when the destructors are declared as virtual, AND when i'm removing the doubles in the Complex class, there is no segmentation fault and the destructors are called in the expected order (Complex, Number), So i guess the problem is related to the size of the object, can anyone please give me an explanation? Thanks, Amit.


Number *numArr = new Complex [2];
delete [] numArr;

Actually, the delete operation invokes undefined behaviour.

§5.3.5/3 says,

In the first alternative (delete object), if the static type of the operand is different from its dynamic type, the static type shall be a base class of the operand’s dynamic type and the static type shall have a virtual destructor or the behavior is undefined. In the second alternative (delete array) if the dynamic type of the object to be deleted differs from its static type, the behavior is undefined.)

What it actually means is this:

Number *object= new Complex();
delete object; //well-defined

//BUT
Number *array = new Complex[N];
delete [] array; //undefined


You cannot have polymorphic arrays in C++. Arrays rely on pointer arithmetic and pointer arithmetic relies on the compiler knowing object sizes. Any access to any element of the array beyond the zeroth is undefined in your case.


I'm not entirely sure, but this is what I suspect...

I wonder if this is related to the fact that an array of derived classes should not be casted to an array of base classes (they're not the same, see: http://www.parashift.com/c++-faq-lite/proper-inheritance.html#faq-21.3): how would delete know the size of the object it is deleting, to adjust the pointer for numArr[0] and numArr[1] (to find the v-table and pass this to the d-tor)

Apparently, the standard explicitly names this as undefined (5.3.5):

In the second alternative (delete array ) if the dynamic type of the object to be deleted differs from its static type, the behavior is undefined.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜