不要用多态方式处理数组以及数组的析构

本文探讨了C++中使用多态处理数组时出现的崩溃问题,特别是通过基类指针删除派生类数组时导致的未定义行为。文章通过一个具体的代码示例分析了问题的原因,并解释了C++标准对此的规定。

今天Jackxu贴了一段代码说有一个奇怪的崩溃,希望一起看看,于是一研究了一下,代码如下,coredump崩溃的地方在delete,编译器是gcc 4.1.2版本。同时在visual studio 上,这个没有错误。崩溃前也没有任何输出。

#include<stdio.h>

class Base

{

char sz[12];

public:

virtual ~Base()

{

printf("Base::~Base/n");

}

};

class Parent: public Base{

bool c;

public:

~ Parent ()

{

printf("Parent::~Parent /n");

}

};

int main()

{

Base* p = new test[2];

delete[] p;

return 0;

}

初看了半天没有发现问题。后来贴到群里,让大家看。几个小伙子提醒是Base* p = new test[2]; 导致的问题,我居然想了半天为啥不准这样用呢。(快一年没有写C++代码了,反映有点迟钝,丢人显眼了)。

经过多方提醒,才突然想起了这样的base类的指针在++处理过程中应该是有问题的,因为指针无法知道自己应该塑形成子类指针,结构就会导致delete 了一个无效的地址,导致崩溃。其实More Effective C++对这个问题是有说明的。详见条款3,不要用多态处理数组。C++语言规格说,通过base类指针删除一个由dreived class 对象构成的数组,结果未定义。

反馈给Jack,Jack又提出如果delete第二个位置的指针导致崩溃,为啥一行打印信息没有输出,回头看看代码发现,的确是,如果第一个变量已经析构,那么就应该Base::~Base 就应该得到输出呀。Sriver用代码输出给出了析构顺序,发现数组是从后面开始调用析构函数的。先以为这个是编译器自己的实现导致的,google了一下,发现这个倒是C++标准,数组构造函数调用的时候顺序调用,析构的时候,反向调用。由于GCC的实现,Base指针指向的数组最后一个位置就是错误的,所以还没有任何输出就崩溃了。

感谢yunfeiyang, liangfeng , sriverxiao, kliu , djiang等同事,每次C++的多态析构总能让我栽跟头,而且很多事情只有在栽了跟头才回真正记得牢。

2011年3月31日星期四,又开始回头看点技术的东西

【本文作者是fullsail(雁渡寒潭),本着自由的精神,你可以在无盈利的情况完整转载此文档,转载时请附上BLOG链接:http://blog.youkuaiyun.com/fullsail,否则每字一元不讲价。对Baidu文库加价一倍】

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值