虚拟dtor分段错误

发布于 2024-12-06 13:15:47 字数 928 浏览 1 评论 0原文

我在 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; 
}

当析构函数被声明为虚拟时,应用程序将因分段错误而退出。当它未声明为虚拟时,将调用 Number 类析构函数(这很明显......)。但是,当析构函数被声明为虚拟时,并且当我删除 Complex 类中的双精度数时,不存在分段错误,并且析构函数按预期顺序(Complex,Number)调用,所以我猜问题是相关的关于物体的大小,有人能给我解释一下吗? 谢谢, 阿米特。

I've got the 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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

青衫儰鉨ミ守葔 2024-12-13 13:15:47
Number *numArr = new Complex [2];
delete [] numArr;

实际上,删除操作会调用未定义的行为。

§5.3.5/3 说,

在第一种选择(删除对象)中,如果操作数的静态类型与其动态类型不同,则静态类型应是操作数动态类型的基类,并且静态类型应具有虚拟析构函数或行为未定义。 在第二种选择(删除数组)中,如果要删除的对象的动态类型与其静态类型不同,则行为未定义。

它的实际含义是这样的:

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

//BUT
Number *array = new Complex[N];
delete [] array; //undefined
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
隔纱相望 2024-12-13 13:15:47

C++ 中不能有多态数组。数组依赖于指针算术,而指针算术则依赖于编译器了解对象大小。在您的情况下,对数组中第零个之外的任何元素的任何访问都是未定义的。

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.

牵你的手,一向走下去 2024-12-13 13:15:47

我不完全确定,但这就是我怀疑的......

我想知道这是否与以下事实有关:派生类数组不应转换为基类数组(它们不一样,请参阅:http://www.parashift.com/c++-faq-lite/proper-inheritance.html#faq-21.3):delete 如何知道大小正在删除的对象,调整 numArr[0]numArr[1] 的指针(找到 v-table 并传递 this 到d-tor)

显然,标准明确将其命名为未定义(5.3.5):

在第二种选择(删除数组)中,如果要删除的对象的动态类型与其静态类型不同,则行为未定义。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文