【问题标题】:Segmentation fault after delete[] on base class pointer [duplicate]在基类指针上删除 [] 后出现分段错误 [重复]
【发布时间】:2018-06-16 16:12:56
【问题描述】:

我这里有一段代码,我不明白为什么它会导致第 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 类没有任何成员变量(即我注释掉“float b;”行),那么代码就可以正常运行。

我的错误是什么?

【问题讨论】:

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


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

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

    实际上,当您没有添加 float 时,您的实现可能会保持 sizeof(B) == sizeof(A)。因此,析构函数和释放函数调用不会立即产生任何有害的影响。但它同样未定义。

    【讨论】:

    • 我以为这就是虚拟析构函数的用途?所以我认为虚拟析构函数只适用于 new/delete,但不适用于 new[]/delete[]?
    • @user3617992 - 虚拟析构函数用于指向单个对象的指针。数组不是多态类型。
    • @user3617992 是的,这就是虚拟析构函数的用途,但是当数组包含与delete 运算符期望不同的项目时,它们无法正确调用。
    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-12-22
      • 2018-07-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-13
      • 2011-04-30
      相关资源
      最近更新 更多