Archive

Archive for April, 2013

记录一个关于C++里面delete[]的事情

April 30th, 2013 No comments

在网上看到一篇“C++的数组不支持多态”?,写的是在使用delete[] 删除一个数组的时候的虚析构函数的调用问题。
大致故事是这样的,首先见如下代码。

include < iostream >

using namespace std;
class Base
{
public:
virtual ~Base() { cout<<“Base”< int a;
};
class Derived : public Base
{
public:
virtual ~Derived() { cout <<“Derived”< int a;
int b;
int c;
};
void test( Base* b)
{
delete[] b;
}
int main(int argc, char* argv[])
{
cout<<“size(Base)”<virtualarray.exe
size(Base)4 size(Derived)16
Derived
Base
Derived
Base
Derived
Base
Derived
Base
Derived
Base
Derived
Base
Derived
Base
Derived
Base
Derived
Base
Derived
Base

而在g++下面程序会崩溃掉。
~/Downloads$ ./test
size(Base)8 size(Derived)20
Segmentation fault (core dumped)

但是在clang++下面的表现让人不是很明白,居然是调用了析构函数,但是只是调用了基类的析构函数
~/Downloads$ ./test
size(Base)8 size(Derived)20
Base
Base
Base
Base
Base
Base
Base
Base
Base
Base

VC一向都比较喜欢帮助大家,所以看起来VC知道你的真正意图是想以sizeof(Derived)为步长去做析构,所以可以跑出这样的结果
在g++下面程序会crash这个很正常,按照delete[] base这一句要表达的是在base所指向的地址上开始析构一个数组,数组的大小记录在base-4的地址上,在这里是10个, 接下来就按照sizeof(Base)为步长,不断的查找虚表并且调用相应的析构函数。但是很不幸base实际上指向的是Derived实例化出来的数组,真正的步长应该是sizeof(Derived).所以上面查找析构函数的地址就肯定是错的。那么崩溃也就在所难免了。 这个是真实的反应出了这个C++语句的本身含义。
而在clang++下面,从输出结果来看,其查找步长似乎是正确的,但是为何调用的是Base的析构而不是Derived的析构则实在是让人不解。

Categories: programming Tags: