在基数 class 指针上删除 [] 后出现分段错误
Segmentation fault after delete[] on base class pointer
我这里有一段代码,我不明白为什么它会导致第 22 行(delete[] 语句)出现分段错误。你能给我解释一下吗?
#include<iostream>
#include<memory>
class A {
size_t a[1000];
public:
virtual ~A() { }
};
class B : public A {
public:
float b;
virtual ~B() { }
};
int main(int argc, char** argv){
A *b;
b = new B[10];
delete[] b;
return 0;
}
奇怪的是,如果 class B 没有任何成员变量(即我注释掉 "float b;" 行)那么代码就可以正常运行。
我这里有什么错误?
delete[] b;
将尝试删除 A 对象数组,而不是 B 对象数组。如果 class B
没有任何成员变量,那么这些数组的大小恰好相同,这可能会让你躲过一劫。
当调用delete
时,它将访问存储在数组中的每个项目的虚表以调用虚拟析构函数。它将假定每个项目的大小为 sizeof(A)
,因此如果 sizeof(B)
不同,则将以错误的偏移量执行访问第二个项目的 vtable。
简而言之,您有未定义的行为。您没有向 delete[]
提供从 new[]
获得的指针。你可能认为你这样做,但要使数组版本中的指针相同,它们的静态类型必须匹配。您将指针转换为指向基数 class.
的指针
实际上,当您没有添加 float
时,您的实现可能会保持 sizeof(B) == sizeof(A)
。所以析构函数和释放函数调用不会立即造成任何伤害。但它同样未定义。
如果你想要数组的多态性,那么你需要创建一个 指向基 class.
的指针的数组
我这里有一段代码,我不明白为什么它会导致第 22 行(delete[] 语句)出现分段错误。你能给我解释一下吗?
#include<iostream>
#include<memory>
class A {
size_t a[1000];
public:
virtual ~A() { }
};
class B : public A {
public:
float b;
virtual ~B() { }
};
int main(int argc, char** argv){
A *b;
b = new B[10];
delete[] b;
return 0;
}
奇怪的是,如果 class B 没有任何成员变量(即我注释掉 "float b;" 行)那么代码就可以正常运行。
我这里有什么错误?
delete[] b;
将尝试删除 A 对象数组,而不是 B 对象数组。如果 class B
没有任何成员变量,那么这些数组的大小恰好相同,这可能会让你躲过一劫。
当调用delete
时,它将访问存储在数组中的每个项目的虚表以调用虚拟析构函数。它将假定每个项目的大小为 sizeof(A)
,因此如果 sizeof(B)
不同,则将以错误的偏移量执行访问第二个项目的 vtable。
简而言之,您有未定义的行为。您没有向 delete[]
提供从 new[]
获得的指针。你可能认为你这样做,但要使数组版本中的指针相同,它们的静态类型必须匹配。您将指针转换为指向基数 class.
实际上,当您没有添加 float
时,您的实现可能会保持 sizeof(B) == sizeof(A)
。所以析构函数和释放函数调用不会立即造成任何伤害。但它同样未定义。
如果你想要数组的多态性,那么你需要创建一个 指向基 class.
的指针的数组