C++关键字operator delete异常分析解答

C 中delete表达式执行的操作是:1,调用析构函数;2,释放对象内存(operator delete(…))。

如果父类的析构函数没有声明为virtual函数,且子类中至少存在一个virtual函数,此时将子类的对象地址赋值给父类指针。当对父类的指针执行delete操作时,会调用父类析构函数,然后在释放内存时(即delete表达式执行的操作的2,释放对象内存)出现崩溃。

然而如果子类中不存在一个virtual函数时,执行上面同样的操作就不会出现崩溃。

原因分析如下:
//已知本示例 父类的析构函数应声明为virtual函数。但是由于本程序不需要析构函数执行特殊的操作,所以delete父类指针pB同样可以释放内存,然而引起出乎意料的内//存释放异常。因此对本程序进行如下分析

#include<iostream>
#include <cstdio>
using namespace std;

class Base
{
public:
~Base() {printf(“nBase::destructor.”);}
};

class Derived: public Base
{
virtual void show()
{
cout<<“show”<<endl;
}
public:
~Derived(){printf(“nDerived::destructor.”);}
};

int main()
{
Base* pB=NULL;
Derived *pD= new Derived;
pB=pD;//此时pD得到的是(unsigned char*)pD 4的地址,所以执行operator delete时会发生崩溃(因为此时把vptr的内存当成了待释放的内存块的大小)。
/*unsigned char *pC=(unsigned char*)pB;
pC=pC-4;
delete pC;//这样就可以释放new Derived分配的内存,而不会发生崩溃。
*/
delete pB;
}

其main函数对应的汇编代码如下(VC6.0):
int main()
{
00401060 push ebp
00401061 mov ebp,esp
00401063 push 0FFh
00401065 push offset __ehhandler$_main (00416a0b)
0040106A mov eax,fs:[00000000]
00401070 push eax
00401071 mov dword ptr fs:[0],esp
00401078 sub esp,64h
0040107B push ebx
0040107C push esi
0040107D push edi
0040107E lea edi,[ebp-70h]
00401081 mov ecx,19h
00401086 mov eax,0CCCCCCCCh
0040108B rep stos dword ptr [edi]

Base* pB=NULL;
0040108D mov dword ptr [ebp-10h],0
Derived *pD= new Derived;
00401094 push 4
00401096 call operator new (00403780)
0040109B add esp,4
0040109E mov dword ptr [ebp-1Ch],eax //eax保存的是operator new(…)函数分配的内存的首地址。
004010A1 mov dword ptr [ebp-4],0
004010A8 cmp dword ptr [ebp-1Ch],0 //判断operator new(…)函数分配内存是否成功。
004010AC je main 5Bh (004010bb)
004010AE mov ecx,dword ptr [ebp-1Ch] //调用Derived::Derived()函数,ecx保存的是内存指针。
004010B1 call @ILT 35(Derived::Derived) (00401028)
004010B6 mov dword ptr [ebp-28h],eax
004010B9 jmp main 62h (004010c2)
004010BB mov dword ptr [ebp-28h],0
004010C2 mov eax,dword ptr [ebp-28h]
004010C5 mov dword ptr [ebp-18h],eax
004010C8 mov dword ptr [ebp-4],0FFFFFFFFh
004010CF mov ecx,dword ptr [ebp-18h]
004010D2 mov dword ptr [ebp-14h],ecx
pB=pD;
004010D5 cmp dword ptr [ebp-14h],0
004010D9 je main 86h (004010e6)
004010DB mov edx,dword ptr [ebp-14h]
004010DE add edx,4
004010E1 mov dword ptr [ebp-2Ch],edx
004010E4 jmp main 8Dh (004010ed)
004010E6 mov dword ptr [ebp-2Ch],0
004010ED mov eax,dword ptr [ebp-2Ch]
004010F0 mov dword ptr [ebp-10h],eax //pB=(unsinged char*)(pD) 4

delete pB;
004010F3 mov ecx,dword ptr [ebp-10h]
004010F6 mov dword ptr [ebp-24h],ecx
004010F9 mov edx,dword ptr [ebp-24h]
004010FC mov dword ptr [ebp-20h],edx
004010FF cmp dword ptr [ebp-20h],0
00401103 je main 0B4h (00401114)
00401105 push 1
00401107 mov ecx,dword ptr [ebp-20h]
0040110A call @ILT 20(Base::`scalar deleting destructor

时间: 2024-08-01 20:35:49

C++关键字operator delete异常分析解答的相关文章

如何做好关键字难易程度分析

关键字的竞争度分析事关SEO大局,在SEO操作过程中非常重要的一个环节,只有在确定好关键字之后,网站架构,页面优化,关键字布局,内容的创建,已经内外链接的创建才更加行之有效.但是,在实际操作的同事,往往对关键字难易程度的分析容易被忽视. 纠结这么久,关键字的难易程度到底应该如何分析?分析哪些维度?接下来裴涛通过实战的方式跟大家分享. 维度一:网站首页的数量 在网站天生的权重上面,通常情况网站的权重应该是首页→栏目/列表→文章页依次递减   那么我们可以得出,某个关键字搜素结果中 1.排名前10名

类的operator new与operator delete的重载

为什么有必要写自己的operator new和operator delete? 答案通常是:为了效率. 缺省版本的operator new是一种通用型的内存分配器,它必须可以分配任意大小的内存块.同样,operator delete也要可以释放任意大小的内存块.operator delete想弄清它要释放的内存有多大,就必须知道当初operator new分配的内存有多大.有一种常用的方法可以让operator new来告诉operator delete当初分配的内存大小是多少,就是在它所返回的

MySQL · 捉虫动态 · MySQL 外键异常分析

外键约束异常现象 如下测例中,没有违反引用约束的插入失败. create database `a-b`; use `a-b`; SET FOREIGN_KEY_CHECKS=0; create table t1(c1 int primary key, c2 int) engine=innodb; create table t2(c1 int primary key, c2 int) engine=innodb; alter table t2 add foreign key(c2) referen

mysql 查询结果异常分析

title: MySQL · mysql · mysql 查询结果异常分析 author: 张远 现象 查询条件类型变化后,查询出了不正确的结果. create table t1(id int primary key, a varchar(50) DEFAULT NULL, key idx_a(a)) engine=innodb; show create table t1; insert into t1 values(1,'6036000240201612190005565273'); inse

SSRS 2008 ReportServerTempDB增长异常分析

  这两天收到一SQL 2008 R2数据库服务器的磁盘空间告警,在检查过程中发现ReportServerTempDB已经暴增到60多GB,其中数据文件接近60G,日志文件9G大小左右.如下截图所示 我 们知道ReportServerTempDB是SSRS使用的临时数据库.这个数据库负责存储中间处理结果,例如报表服务器生成的会话和执行数据.缓存报 表以及工作表.正常情况下,Report Server能够周期性地清除ReportServerTempDB中的到期的和孤立的数据.后台进程定期清理时间间

异常分析初探

异常在Java中是非常重要的一个内容,了解异常有助于我们写出更加健壮的代码,本文将探讨一下几个问题: 1 异常是怎么被JVM捕获的? 2 新建异常实例是否耗时?为什么会耗时?是否能够避免? 3 为什么不推荐使用printStackTrace()打印异常信息? 4 spring jdbc运行时异常种类概要 5 什么时候应该抛出数据库运行时异常 1. 异常怎么被JVM捕获的 在了解这个之前首先介绍下java的异常表(Exception table),异常表是JVM处理异常的关键点,在java类中的每

HybridDB · 源码分析 · MemoryContext 内存管理和内存异常分析

背景 最近排查和解决了几处 HybridDB for PostgreSQL 内存泄漏的BUG.觉得有一定通用性. 这期分享给大家一些实现细节和小技巧. 阿里云上的 HybridDB for PostgreSQL 是基于 PostgreSQL 开发,定位于 OLAP 场景的 MPP 架构数据库集群.它不少的内部机制沿用了 PostgreSQL 的实现.其中就包括了内存管理机制 MemoryContext. 一:PostgreSQL 内存管理机制 PostgreSQL 对内存的使用方式主要分两大块

WCF异常分析

WCF的代码实例网上到处都是,但是在实际的使用过程中总会出现很多问题,我就我在项目中使用WCF碰到的问题做个总结: (注:要看到服务端真正异常配置includeExceptionDetailInFaults="true") 一.现象:界面假死不抛出任何异常(按常理超过等待时间应该抛出超时异常但是没有抛出不知道是什么原因)或抛出超时异常. 代码环境:WinForm+netTcpBinding. 原因分析:因为netTcpBinding和wsHttpBinding都是有状态连接所以造成这种

Linux内核中断和异常分析(上)

中断,通常被定义为一个事件.打个比方,你烧热水,水沸腾了,这时候你要去关掉烧热水的电磁炉,然后再去办之前手中停不下来的事情.那么热水沸腾就是打断你正常工作的一个信号机制.当然,还有其它的情况,我们以后再做分析.       中断也就是这样产生的,中断分为同步中断还有异步中断.       同步中断在Intel的手册中被称为异常,而异步中断被称作中断.打个比方在ARM处理器的异常种类就有不少,有未定义指令异常,软中断异常,快中断异常等等.异常是由程序错误产生的,或者是内核必须处理的异常条件产生的.