在基数 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.

的指针的数组