首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Virtual dtor分段故障

Virtual dtor分段故障
EN

Stack Overflow用户
提问于 2011-09-26 02:16:04
回答 3查看 581关注 0票数 2

我用C++编写了以下代码:

代码语言:javascript
复制
#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; 
}

当析构函数被声明为虚拟时,应用程序将因分段错误而退出。当它没有声明为virtual时,就会调用Number类的析构函数(这是显而易见的……)。但是,当析构函数被声明为虚拟的,当我删除复杂类中的doubles时,没有分段错误,析构函数是按照预期的顺序( Complex,Number)调用的,所以我猜问题与对象的大小有关,有人能给我一个解释吗?谢谢,阿米特。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-09-26 02:24:04

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

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

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

如果要删除的对象的动态类型与其静态类型不同,则行为在fined下。

票数 2
EN

Stack Overflow用户

发布于 2011-09-26 02:27:39

代码语言:javascript
复制
Number *numArr = new Complex [2];
delete [] numArr;

实际上,delete操作调用的是未定义的行为。

§5.3.5/3表示,

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

它的实际含义是:

代码语言:javascript
复制
Number *object= new Complex();
delete object; //well-defined

//BUT
Number *array = new Complex[N];
delete [] array; //undefined
票数 6
EN

Stack Overflow用户

发布于 2011-09-26 02:36:03

在C++中不能有多态数组。数组依赖于指针算法,而指针算法依赖于知道对象大小的编译器。在您的例子中,对第零位以外的任何数组元素的访问都是未定义的。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7547538

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档