基类指针上的delete []之后的分段错误

时间:2018-01-07 13:19:48

标签: c++ segmentation-fault delete-operator

我这里有一段代码,其中我不明白为什么它会导致第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;
}

奇怪的是,如果B类没有任何成员变量(即我注释掉了行&#34;浮动b;&#34;)那么代码运行正常。

我的错误是什么?

3 个答案:

答案 0 :(得分:11)

简单地说,你有未定义的行为。您无法向delete[]提供您从new[]获得的指针。您可能认为这样做,但是对于数组版本中的指针,它们的静态类型必须匹配。您将指针转换为指向基类的指针。

实际上,如果您没有添加float,那么您的实施可能会保留sizeof(B) == sizeof(A)。所以析构函数和释放函数调用不会立即做任何有害的事情。但它同样未定义。

答案 1 :(得分:3)

delete[] b;将尝试删除A对象的数组,而不是B对象的数组。如果类B没有任何成员变量,那么这些数组的大小恰好相同,这可能会让你躲避子弹。

当调用delete时,它将访问存储在数组中的每个项目的vtable以调用虚拟析构函数。它将假设每个项目的大小为sizeof(A),因此如果sizeof(B)不同,则访问第二项的vtable将在错误的偏移处执行。

答案 2 :(得分:1)

如果你想要一个数组的多态性,那么你需要创建一个指向基类的指针数组