虚拟dtor分段错误
我在 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
实际上,删除操作会调用未定义的行为。
§5.3.5/3 说,
它的实际含义是这样的:
Actually, the delete operation invokes undefined behaviour.
§5.3.5/3 says,
What it actually means is this:
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.
我不完全确定,但这就是我怀疑的......
我想知道这是否与以下事实有关:派生类数组不应转换为基类数组(它们不一样,请参阅: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 fornumArr[0]
andnumArr[1]
(to find the v-table and passthis
to the d-tor)Apparently, the standard explicitly names this as undefined (5.3.5):