不要用基指针删除派生对象数组

看陈皓的博客后,发现这一点,以前都没注意过,也是因为没这样用过

陈皓叔 R.I.P...

见下面代码:

#include <iostream>

class Base {
  int b;

 public:
  virtual ~Base() { std::cout << "B::~B()" << std::endl; }
};

class Derived : public Base {
  int i;
  int j;

 public:
  virtual ~Derived() { std::cout << "D::D~()" << std::endl; }
};

int main() {
  std::cout << "sizeB:" << sizeof(Base) << " sizeD:" << sizeof(Derived)
            << std::endl;
  Base* pBase = new Derived[10];
  delete[] pBase;

  return 0;
}

在 windows 上,visual studio 可以编译通过并运行成功

在 linux 上,clion 编译通过,但是运行报错

因为 vs 编译器默认了这个未定义行为,把恶果自己吞下去了但不告诉我们

为什么不可以用基类指针析构数组,文章有很好的解释

因为 sizeof(B):16 ,sizeof(D):24。pb[1] 的虚表找到了一个错误的内存上,内存乱掉了 (x86 上两个类的 sizes 是 8 和 16)

主要问题是内存对齐上,导致基类指针不能准确的找到派生类的成员的地址,导致析构出错

上面派生类删掉 int j,就可以正常运行,因为 size 大小一样了(仅限 clion 上),vs 上还是显示的不一样

相关的帖子:

posted @ 2023-06-21 16:23  strive-sun  阅读(12)  评论(0编辑  收藏  举报