今天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.csdn.net/fullsail,否则每字一元不讲价。对Baidu文库加价一倍】