https://www.zhihu.com/question/30838092/answer/49623765

C++通过基类指针delete派生类数组,析构函数是虚函数,程序为什么会崩溃?

代码如下

#include<iostream>
using namespace std;class base{public:virtual ~base(){}
};class derived:public base{int a;
};int main(){base *p=new derived[10];delete[] p;return 0;
}

举报

7 条评论

分享

查看全部 10 个回答

28赞同 反对,不会显示你的姓名
bryantism,给我一个理由忘记
weyou、刘源、任思远 等人赞同

c++ 03 5.3.5

In the first alternative (delete object), if the static type of the object to be deleted is different from its dynamic type, the static type shall be a base class of the operand’s dynamic type and the static type shall have a virtual destructor or the behavior is undefined. In the second alternative (delete array) if the dynamic type of the object to be deleted differs from its static type, the behavior is undefined.

编辑于 2015-05-31 7 条评论 感谢

分享

收藏 • 没有帮助 •

举报

• 作者保留权利

更多回答
98赞同 反对,不会显示你的姓名
vczh,专业造轮子,http://www.gaclib.net
李嘉图、赖威、李国宝 等人赞同

在某些实现里,base4个字节,derived8个字节,你new了一个80个字节的derived*数组然后当base*干掉,那么要么它就会执行析构函数20次然而有10个this指针式不对的,要么他会执行10次然而有5个this指针是不对的。自然要挂。

然而在VC++下面却没问题,因为VC++的实现是记录了array的个数和每个对象的大小,他不会因为你把数组搞成了base*就真的以为他是base[],所以会执行10次析构函数,10次的this指针都对。

为什么错误的this指针就会挂呢?因为从base调用derived::~derived函数的方法,是先把一个固定的数字加到this指针上面得到一个全局的代表derived在base上面的虚函数表,然后再虚函数表里面找到析构函数的指针,最后执行它。如果你的this有问题,那中间有一步就会dereference失败,自然AV。

Edward
不明觉屌啊……
2015-06-01   2 赞

何磊
执行10次但是有5个this指针是不对的,为什么啊?
2015-06-01   

Warthog
这么正经的回答居然没几个人评论。。。
2015-06-01   1 赞

尤不二 回复 何磊
执行10次的情况是:删除了10个4byte,每两个4byte指向的是正确的derived,自然有一半的this是错的
2015-06-01   

fx991ESplus 回复 何磊
sizeof(base)是4,sizeof(derived)是8呗
2015-06-01   

莫惜培
某些实现,话里有话啊
2015-06-01   

何磊 回复 尤不二
懂了,谢谢
2015-06-01   

孙明琦
还是vc的扩展厉害
2015-06-01   

许镇
轮子哥一正经起来我就看不懂了
2015-06-01   1 赞

洛漓
0.0轮子哥貌似很推崇VC++
2015-06-01   

fx991ESplus 回复 莫惜培
g++……
2015-06-01   

汪堇年
不信linux环境下会有问题
2015-06-01   

vczh(作者) 回复 汪堇年
呵呵
2015-06-01   

从此寂静无声
学习了
2015-06-01   

周翀
仅就这个特例来说,后十次,编译器应该是call十次base::~base并压入“错误”的this(实际也没太错),然后dtor里面也没碰this,为啥还会crash?
2015-06-02   

vczh(作者) 回复 周翀
因为dtor是虚函数
2015-06-02   

周翀 回复 vczh(作者)
……哦,靠!(逃……
2015-06-02   

李爱吉
只是, msvc的实现的是对标准的扩充, 方言特性不具备移植性
2015-06-02   

Warthog 回复 柯基屁
这是C++的基础知识啊
2015-06-02   1 赞

汪堇年 回复 vczh(作者)
挂一下代码吧
2015-06-02   

Warthog 回复 柯基屁
果然他的脑残粉不会写代码的比会写代码的多一个数量级。。
2015-06-02   

Warthog 回复 柯基屁
因为就是脑残粉啊
2015-06-02   

飞大郎
虽然一句也看不懂,依然要点赞。
2015-06-02   

Warthog 回复 柯基屁
I don't give a fuck
2015-06-02   

王星
一个都看不懂
2015-06-03   

汪良
“然而在VC++下面却没问题”
2015-06-03   

汪良
刚试了下,g++ 5.1.0 不行,clang++ 3.5.0 没出现问题。
2015-06-03 回复 赞 

C++通过基类指针delete派生类数组,析构函数是虚函数,程序为什么会崩溃? https://www.zhihu.com/question/30838092/answer/49623765相关推荐

  1. 基类指针调用派生类函数_C++ 多态性:虚函数--基类与派生类类型转换(第7章 05)例子问题解析(学习笔记:第8章 05)...

    虚函数[1] 问题:还记得第7章的例子吗[2]? 例7-3 类型转换规则举例 #include <iostream> using namespace std; class Base1 { ...

  2. C++基类指针指向派生类(指针)

    我们常用基类指针指向派生类对象来实现多态性. 私有继承不允许基类指针指向派生类 基类指针只能访问到基类中含有的公有成员. 当用基类指针指向派生类对象在动态分配堆上内存的时候,析构函数必须是虚函数! 成 ...

  3. C++的基类指针指向派生类对象,vector实现多态性

    添加问题: 练手创建一个表示各种不同包裹的继承层次. 在写代码时:要求vector来实现多态性 , 用基类指针变量指向子类对象. 前面的父类和子类定义: //创建一个表示各种不同包裹的继承层次 #in ...

  4. C++>继承,继承方式及其比较,子类和父类对象指针,派生类的默认成员函数,虚继承,继承与友元,继承与静态成员

    继承 继承的概念与定义 概念: 继承是指一个子类(或称为派生类)继承父类(或称为基类)的特征(属性和操作).继承是面向对象程序设计时实现代码复用的重要手段,它允许在原有的类的基础上进行扩展,增加功能, ...

  5. 基类对象与派生类对象的关系

    点击打开原文链接 基类对象与派生类对象的使用关系 1. 派生类对象作为基类对象处理 由于派生类具有所有基类的成员,所以把派生类的对象赋给基类对象是合理的,不过要求这种继承方式必须是public方式.但 ...

  6. 不同派生方式下基类成员在派生类中的可访问范围属性

    不同派生方式下基类成员在派生类中的可访问范围属性 派生方式 派生方式 派生方式 基类成员 公有派生 私有派生 保护派生 私有成员 不可访问 不可访问 不可访问 保护成员 保护 私有 保护 公有成员 公 ...

  7. 虚函数之定义一个基类Shape,在此基础上派生出Rectangle和Circle再使用Rectangle类创建一个派生类Square。

    定义一个基类Shape,在此基础上派生出Rectangle和Circle,二者都有getArea( )函数计算对象的面积,再使用Rectangle类创建一个派生类Square.将getArea()改造 ...

  8. C++实例:基类BaseClass,派生类DerivedClass

    1.问题描述 定义一个基类BaseClass,从它派生出类DerivedClass,BaseClass有成员函数fn1().fn2(),DerivedClass也有成员函数fn1().fn2(),在主 ...

  9. C++改变基类成员在派生类中的访问属性

    使用using声明可以改变基类成员在派生类中的访问属性.我们知道基类的公有成员经过公有继承,在派生类中其属性为public的,但是通过using 声明,我们可以将其改为private或protecte ...

最新文章

  1. (0069)iOS开发之dequeueReusableCellWithIdentifier的两个方法的区别
  2. 编程十年 (2):前传2——哪有这么牛逼的游戏机?
  3. Xavier初始化和He初始化
  4. Java11安装及环境变量设置
  5. object detection
  6. 如何恢复在 PyCharm 中误删的整个项目文件
  7. oracle 查看数据库性能,oracle 11G使用statspack查看数据库的性能
  8. 在Javascript中闭包(Closure)
  9. flask response响应
  10. Error message: Make sure that `gem install pg -v '0.18.3'` succeeds before bundling
  11. HTML5 开发工具
  12. FTDI的LibMPSSE编译流程
  13. SpringBoot入门到精通 idea教学 (余胜军通俗易懂版本)
  14. OnlyOffice官方Demo必要的修改及参数解释
  15. MFC C++ 中的内存释放问题
  16. 项目文件快速搜索神器
  17. java考了80多分,八省联考成绩出炉,学生们表示“有些崩溃”,你考了多少分
  18. javaweb基于SSM开发学生请假管理系统 课程设计 毕业设计源码
  19. 网页设计-第四次作业
  20. adjacent angle_帝学教育:新SAT数学词汇中英文对照(几何篇)

热门文章

  1. 软件生存周期与开发模型
  2. 带管理口的mellanox交换机开启端口一分二特性
  3. (每日一练C++)CC211 整数对查找
  4. 【vue】vue商城设计-模仿京东商城
  5. 图像二值化的阈值求法
  6. Oracle坑点大全
  7. 测试案例编写规范总结
  8. SCJP认证复习~1
  9. 06.前端之BootStrap
  10. 【Bard vs. GPT-4】谷歌一雪前耻!全新PaLM 2反超GPT-4,办公全家桶炸裂升级,Bard史诗进化