你好,欢迎来到电脑编程技巧与维护杂志社! 杂志社简介广告服务读者反馈编程社区  
合订本订阅
 
 
您的位置:杂志经典 / 编程语言
解析VC6.0中为类对象申请内存的过程(十四)
 

顺着看下来一直到004021C9,这句过后可得出ECX里存放的是pItem指向的地址。紧接着一直到004021D0,它是对类析构函数的调用。再向下看程序只做了一些检查就直接调用了释放内存的调用,这也能解释为什么能看到那一句输出。再想想上面一起讨论了new的过程,pItem指向的地址向前4字节才是new所得内存的开始,但看004021E2这句它直接把pItem指向的地址传给了释放内存的调用,这当参数当然不是一个有效的内存块的起始地址了。如果深入跟踪的话可以了解到在debug版本在堆内存的管理中,为每一块申请的内存建立了一个链表项并存放在一个链表中,释放时就去链表里找。而传入的那个地址显然不是一个已申请内存块的正确地址,所以系统会报错。

在上面实验的类中把CMemoryItem析构函数的virtual修饰符去掉,现在再把它加做上面的实验看一下情况会有变化吗?在析构函数中加不加virtual修饰符真的在释放时没有差别吗?那么再看一下单个对象的释放。

4.2  解释类对象时的跟踪

同样先把CMemoryItem类的析构函数的virtual修饰符去掉,然后来看两段代码片段的具体执行情况。

代码1

CMemoryItem* pItem = new CMemoryItem;

delete pItem;

执行正常,再看下面的代码。

代码2

CMemoryItem* pItem = new CMemoryItem;

delete[] pItem;

弹出了上面贴出的那个出错框。大家可能觉得这很正常,那来看看一段不正常的。现在再把类析构函数的virtual修饰符加在上面的实验看一下情况。代码1没错(肯定的),再执行代码2也没错。是不是有些奇怪了,为了了解其中原因就看它的汇编代码。下面列出代码:

00401E89   mov         edx,dword ptr [ebp-20h]

00401E8C   mov         eax,dword ptr [edx]

00401E8E   mov         ecx,dword ptr [ebp-20h]

00401E91   call        dword ptr [eax]

EDX ECX存放是的pItem指向的地址,因为这个类的析构函数加了virtual修饰符,那么这个类的前四个字节就是析构函数的指针。00401E91这句也就调用了类的析构函数,这自然不会错。那么为什么类的析构函数不加virtual修饰符时就会出错呢?下面也列出一段汇编代码大家便可明白。

00401E87   mov         ecx,dword ptr [ebp-20h]

00401E8A   call        @ILT+170(CMemoryItem::`vector deleting destructor') (004010af)

类的析构函数不加virtual修饰符时, delete[] pItem;系统把它当成一个对象数组去释放自然会出错。这不是说只要为类的析构函数加了virtual修饰符就可以不分数组还是单个对象都用delete[]释放了。因为不同编译器或相同编译器的不同版会有不同的编译方法,只是对VC6.0编译后的程序做了剖析。

5  结语

这里讨论了VC6.0newdeltte对象的过程,希望能给大家的编程带来一些帮助。
  推荐精品文章

·2024年9月目录 
·2024年8月目录 
·2024年7月目录 
·2024年6月目录 
·2024年5月目录 
·2024年4月目录 
·2024年3月目录 
·2024年2月目录 
·2024年1月目录
·2023年12月目录
·2023年11月目录
·2023年10月目录
·2023年9月目录 
·2023年8月目录 

  联系方式
TEL:010-82561037
Fax: 010-82561614
QQ: 100164630
Mail:gaojian@comprg.com.cn

  友情链接
 
Copyright 2001-2010, www.comprg.com.cn, All Rights Reserved
京ICP备14022230号-1,电话/传真:010-82561037 82561614 ,Mail:gaojian@comprg.com.cn
地址:北京市海淀区远大路20号宝蓝大厦E座704,邮编:100089