软件调试之堆和堆检查

当用户启动一个程序时,系统会将程序文件从外部存储器(硬盘等)加载到内存中。当程序工作时,需要使用内存空间来放置代码和数据。在使用一段内存之前,程序需要以某种方式(API或库函数)发出申请,接受到申请的一方(内存管理器或C运行库)根据申请者的要求从可用(空闲)空间中寻找满足要求的内存区域分配给申请者。当程序不再需要该空间时应该通过与申请方式相对应的方法归还该空间,即释放。

在大型软件项目中,合理分配和释放内存是非常重要的,由于内存使用不当而导致的各种问题经常成为软件项目的严重阻碍。提高内存的使用率,降低内存分配和释放过程的复杂性一直是软件产业中的永恒话题。JAVA和.net语言的一个共同优势就是可以自动回收不再需要的内存,使程序员可以不用编写释放内存的代码。通过栈来分配局部变量也可以看做是简化内存使用的一种方法

堆是组织内存的另外一种重要方法,是程序在运行期动态申请内存空间的主要途径。与栈空间是由编译器产生的代码自动分配和释放不同,堆上的空间需要程序员自己编写代码来申请(HeapAlloc)和释放(HeapFree),而且分配和释放操作应该严格匹配,忘记释放或多次释放都是不正确的

与栈上的缓冲区溢出类似,如果向堆上的缓冲区写入超过其大小的内容,也会因为溢出而破坏堆上其他内容,可能导致严重的问题,包括程序崩溃。

为了帮助发现堆使用方面的问题,堆管理器,编译器和软件类库提供了很多检查和辅助调试机制。比如,Win32支持参数检查,溢出检查及释放检查等功能。VC编译器设计了专门的调试堆并提供了一系列用来追踪和检查堆使用情况的函数,在编译调试版本的可执行文件时,可以使用这些调试支持来解决内存泄漏等问题。


1.理解堆

栈是分配局部变量和存储函数调用参数以及返回位置的主要场所,系统在创建每个线程时会自动为其创建栈。对于C/C++这样的编程语言,编译器在编译阶段会生成合适的代码来从栈上分配和释放空间,不需要程序员编写任何额外的代码,出于这个原因栈得到了“自动内存”的一个美名。

不过从栈上分配内存也有不足之处,首先,栈空间(尤其是内核态栈)的容量是相对较小的,为了防止栈溢出,不适合在栈上分配特别大的内存区其次,由于栈帧通常是随着函数的调用和返回而创建和消除的,因此分配在栈上的变量只是在函数内有效,这使栈只能分配局部变量,不适合分配需要较长生存期的全局变量和对象。第三,尽管也可以使用_alloca()这样的函数来从栈上分配可变长度的缓冲区,但是这样做回给异常处理(EH)带来麻烦,因此栈也不合适分配运行期才能决定大小(动态大小)的缓冲区

从操作系统的角度看,堆是系统的内存管理功能向应用软件提供服务的一种方式。通过堆,内存管理器(Memory Mamager)将一块较大的内存空间委托给堆管理器(Heap Manager)来管理。堆管理器将大块的内存分割成不同大小的很多个小块来满足应用程序的需要。应用程序的内存需求同城是频繁而且零散的,如果把这些请求都直接传递给位于内核中的内存管理器,那必将影响系统的性能。有了堆管理器,内存管理器就只需要处理大规模的分配请求。这样做不经可以减轻内存管理器的负担,也可以大大缩短应用程序申请内存分配所需的时间,提高程序的运行速度。

用户态的代码应该调用虚拟内存分配API来从内存管理器分配内存。虚拟内存API包括VirtualAlloc,VirtualAllocEx,VirtualFree,VirtualFreeEx,VirtualLock,VirtualUnlock,VIrtualProtect,VIrtualQuery。

内核态的代码可以调用以上API所对应的内核函数,如NtAllocateVirtualMemory, NtProtectVirtualMemory。

为了满足内核空间中的驱动程序等内核态代码的内存分配需要,Windows的内核模块中实现了一系列函数来提供内存零售服务,为了与用户空间的堆管理器相区别,这些函数统称为池管理器(Pool Manager)。池管理器公开了一组驱动程序接口(DDI)以向外提供服务,包括ExAllocatePool,ExAllocatePoolWithTag等

http://www.cnblogs.com/CBDoctor/archive/2013/02/20/2918456.html

(备注:虚拟内存API是通过内存管理器从虚拟内存中分配大块的内存)

与内核模块中的池管理器类似,在NTDLL.DLL中实现了一个通用的堆管理器,目的为用户态的应用程序提供内存服务,通常被称为Win32堆管理器。SDK中公开了一组API来访问Win32堆管理器的功能,如HeapAlloc,HeapFree等

为了支持C的内存分配函数和C++的内存分配运算符(new和delete)(统称为CRT内存分配函数),编译器的C运行库会创建一个专门的堆供这些函数所使用,通常称为CRT堆。根据分配堆块的方式不同,CRT堆有三种工作模式:SBH(Small Block Heap),旧SBH(Old SBH)和系统模式(System Hea

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值