内存泄漏的真正含义

来源:互联网 发布:如何查看淘宝通用pid 编辑:程序博客网 时间:2024/06/10 00:15

我们所说的内存泄漏却实是指分配了但不释放的内存,但是称其为“内存泄漏”还有其它的特点:  
  1、指向它的指针已经指向了另一块区域(它被“遗忘”了)  
  2、或者,这段内存会不受控制地增长它的大小(它太“贪婪”)。  

 

如果我写一个程序,分配一大段内存,然后就退出了它,没有释放内存,会有什么动作呢?  
 如果new是一个系统调用,那么就会在系统中留下一些“痕迹”,因为它使用了系统的handle。  
  如果new是一个封装后的调用,而它的基础_crt_heap已经不再了的话,会有什么影响?(系统handle已经关闭了)  
   
  也就是说,当在windows上写一个console程序(在其它操作系统上写以main()开始的程序时也同理)时,只要你使用库函数或new来分配内存,不论你分配多少,程序退出时就会被释放掉。  
   
  用一个笨方法证明:你可以写一个这样的程序,用ShellExecute运行它10000次,再看你的缓存文件+内存大小是不是等于分配内存的10000倍。  
   
  说句实话,如果内存泄漏不增长,它一点也不可怕。因为运行多少年它也是那么大,不会影响到正常使用。等到关机时管它还有没有内存“泄漏”呢!

 

为此,Scott   Mayer还在他的书再版时专门加入了对他写的一段代码的解释,摘录如下(代码从略)  
   
  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////  
  ……  
   
  所有一切都很好,但从你皱起的眉头我可以知道你一定在担心内存泄漏。有着大量开发经验的你不会没注意到,airplane的operator  new调用::operator   new   得到了大块内存,但airplane的operator  delete却没有释放它们。内存泄漏!内存泄漏!我分明听见了警钟在你脑海里回响。  
   
  但请仔细听我回答,这里没有内存泄漏!  
   
 引起内存泄漏的原因在于内存分配后指向内存的指针丢失了。如果没有垃圾处理或其他语言之外的机制,这些内存就不会被收回。但上面的设计没有内存泄漏,因为它决不会出现内存指针丢失的情况。每个大内存块首先被分成airplane大小的小块,然后这些小块被放在自由链表上。当客户调用airplane::operator   new时,小块被自由链表移除,客户得到指向小块的指针。当客户调用operator  delete时,小块被放回到自由链表上。采用这种设计,所有的内存块要不被airplane对象使用(这种情况下,是由客户来负责避免内存泄漏),要不就在自由链表上(这种情况下内存块有指针)。所以说这里没有内存泄漏。  
   
  然而确实,::operator  new返回的内存块是从来没有被airplane::operator  delete释放,这个内存块有个名字,叫内存池。但内存泄漏和内存池有一个重要的不同之处。内存泄漏会无限地增长,即使客户循规蹈矩;而内存池的大小决不会超过客户请求内存的最大值。  
  ……  
   
  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

  其实"内存泄漏"这个名词怎么解释是见仁见智的,  
  有的认为它不包含了内存丢失,像楼主就是这么认为,有的认为  
  它包含内存丢失,像微软。因此内存泄漏到底怎么解释,实际上  
  没有太大的指导意义。关键是要搞清楚怎样正确使用内存,其实  
  内存使用出错一般分为两种:1、是申请(new)并获得了内存但未  
  释放(delete),这种错误如果长时间、反复出现,最终内存会被  
  耗尽,但程序退出时会自动释放。2、是申请内存后,在使用的过  
  程中因为某些原因,致使内存管理(有可能是操作系统的,也有  
  可能是某个语言的具体实现,如VC的内存管理模块)用的数据出  
  错,这种情况发生后即使释放(delete)内存,也有可能无法释放  
  掉,这种情况就是楼主所谓的内存泄漏,内存管理用的数据都出  
  错了,因此什么情况都可能发生。  
          无论哪种情况,在特定的情况下,都会导致严重的后果,因此  
  都应该避免,因此基于这种考虑,我个人认为内存泄露包含内存丢  
  失似乎更好一些,毕竟MS的程序员们都经验丰富。

 

内存泄漏其实不只是new/delete,malloc/realloc/free等一堆造成的,还可能包括OLE的内存泄漏,特别是Com的应用程序,由于都是公用OleAut32的,因此这个部分的内存泄漏是非常重要的,不知道OLE的内存泄漏BoundsCheck能否检查到呢?根据Platform  SDK的提示,那是非常麻烦的(先要创建CMallocSpy,然后需要使用对应checked版本的oleaut32.dll,还有在安装环境下配置,我以前曾经在NT4.0作过,而且记得当时测试出VB6  Sp3的一个内存泄漏--sp5中已经修复了)。更有甚者,是设备的一些内存泄漏,比如Sockect,句柄没释放/线程异常产生的内存泄漏等。这些可能产生的内存泄漏更多。

 

http://topic.csdn.net/t/20020906/16/1002256.html

原创粉丝点击