不要用基指针删除派生对象数组
看陈皓的博客后,发现这一点,以前都没注意过,也是因为没这样用过
陈皓叔 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 上还是显示的不一样
相关的帖子: