windows程序员进阶系列:《软件调试》之堆 (一)
windows程序员进阶系列:《软件调试》之堆 (一)
堆是软件在运行时动态申请内存空间的主要途径。从堆上申请来的空间需要程序员自己申请和释放,且申请和释放操作必须绝对匹配。忘记释放或者多次释放可能会导致严重问题。
与栈类似,使用堆的过程中也会由于向堆中写入超过所申请堆大小的数据,覆盖堆上的其他内容,而导致堆溢出问题。
由于堆的特殊性,一旦堆被破坏将会导致一些严重的问题。由于如果对堆不够了解的话对于这些问题将会手足无措。本文将会详细的介绍堆的方方面面,通过以下几篇文章的讲解便可以很清晰的了解堆的结构,再遇到在堆上出现的问题将从容应对而不再是手足无措。
由于堆的复杂性,本主题将会分五篇文章来介绍。
第一篇文章将介绍堆的基本概念以及堆的分类。
第二篇文章将介绍win32堆的内部结构。
第三篇文章将介绍CRT堆的内部结构。
第四篇文章介绍堆的调试支持。
第五篇文章将分析一个堆破坏的实例。
栈是分配局部变量和函数调用的主要场所。编译器在编译时会生成合适的代码来从栈上分配空间。因此栈又被称为“自动内存”。但是栈也有自己的不足:首先由于栈是非常小的,不适合分配特别大(动辄几十M)的内存区。再者栈会随着函数的调用和返回不断的创建和销毁。因此只适用于局部变量的分配,不适合分配具有长生命周期的变量。
堆克服了以上栈的缺点。应用程序通过HeapAlloc 、malloc、new分配的空间均来自于堆。而它们均是通过堆管理器从堆中分配空间的。堆管理器用于管理堆,对外提供堆分配和释放的接口。
在windows操作系统的内核态有一个管理内存空间的内存管理器。堆管理器管理的空间是通过内存管理器获得的。由于应用程序申请空间的操作可能是分散且零散的,为了避免频繁的向内存管理器申请空间,堆管理器会一次性的向内存管理器批发大量的内存空间,然后零散的分配给应用程序。
有一个形象的比喻:把内存管理器比作内存工厂,对外不接受小批量的订货。而堆管理器是该工厂的代理商,零售给应用程序。
Windows操作系统的堆管理器被称为win32堆管理器,它管理的堆被称为win32堆。
为了支持C/C++的malloc 、new等内存分配函数。编译器的C运行库(CRT)在程序初始化时会创建一个专门的堆供这些函数使用,这个专门的堆被称为CRT堆。
CRT堆有三种工作方式:SBH模式、旧SBH模式和系统模式。
前两种模式时,CRT堆管理器会直接从内存管理器批发内存,然后分割成小块的堆块供应用程序使用。
第三种模式CRT堆管理器会将对堆块的分配请求转发给win32堆管理器。因此处于系统模式的CRT堆仅仅是堆win32堆的简单封装。
除了上面介绍的堆,应用程序也可以实现自己的堆管理器。直接向内存管理器批发内存,供本应用程序内部使用。例如:应用程序通过向内存管理器申请空间,实现的内存池就可以看做是一种堆管理器。
如图所示,应用程序可以从内存管理器、win32堆、CRT堆申请空间。
但三者有区别:
通过内存管理器申请时是调用VirtualAlloc申请的。申请大小是以页面大小(win32下为4KB)为单位。
通过WIN32堆管理器申请时是调用HeapAlloc申请的,但当申请的空间超过一定阈值时,WIN32堆管理器并不会从自己的堆中分配,而是重新向内存管理器申请,然后转交给应用程序。
通过CRT堆申请空间是调用new 、malloc等C/C++函数来实现的。同样当申请的空间超过一定阈值时,会从上一级直接申请并转交给应用程序。根据工作模式的不同,上一级可以是WIN32堆,也可以是内存管理器。
内存管理类似于内存工厂,用于生产内存并向外批量出货。
Win32堆是中间商,直接从内存工厂进货,提供批发和零售服务。
CRT堆是更下一级的中间商,可以从内存工厂和中间商进货,对外提供零售服务。
应用程序是消费者,可以从以上三个角色购买内存。但是只有当购买量很大时才能从内存工厂购买。
如有纰漏,请指正,谢谢!
2013.10.12于浙江杭州
windows程序员进阶系列:《软件调试》之堆 (一)的更多相关文章
- windows程序员进阶系列:《软件调试》之Win32堆的调试支持
Win32堆的调试支持 为了帮助程序员及时发现堆中的问题,堆管理器提供了以下功能来辅助调试. 1:堆尾检查(Heap Tail Check) HTC,在堆尾添加额外的标记信息,用于检测堆块是否溢出. ...
- windows程序员进阶系列:《软件调试》之Win32堆
win32堆及内部结构 Windows在创建一个新的进程时会为该进程创建第一个堆,被称为进程的默认堆.默认堆的句柄会被保存在进程环境块_PEB的ProcessHeap字段中. 要获得_PEB的地址, ...
- Boostnote:适合程序员的笔记软件【转】
本文转载自:https://blog.csdn.net/u013553529/article/details/70306899 Boostnote:适合程序员的笔记软件 注意: Boostnote正在 ...
- PHP程序员进阶学习书籍参考指南
PHP程序员进阶学习书籍参考指南 @heiyeluren lastmodify: 2016/2/18 [初阶](基础知识及入门) 01. <PHP与MySQL程序设计(第4版)> ...
- 谈谈Java程序员进阶的那些知识和方向
谈谈Java程序员进阶的那些知识和方向 记得前段时间看过一篇文章谈到一种程序员叫野生程序员,战斗力极强,可以搞定一切问题,但是通常看问题抓不到本质,或者说是google/baidu/stackover ...
- 程序员面试系列之Java单例模式的攻击与防御
我写的程序员面试系列 Java面试系列-webapp文件夹和WebContent文件夹的区别? 程序员面试系列:Spring MVC能响应HTTP请求的原因? Java程序员面试系列-什么是Java ...
- windows程序员开发linux程序的头一个月
开发环境选择 vim,vscode,qt,visual studio都可以做linux c++开发,但是作为windows程序员,最熟悉的还是visual stuio,加上visual studio ...
- 做10年Windows程序员与做10年Linux程序员的区别(附无数评论)(开源软件相当于熟读唐诗三百首,不会作诗也会吟)
如果一个程序员从来没有在linux,unix下开发过程序,一直在windows下面开发程序, 同样是工作10年, 大部分情况下与在linux,unix下面开发10年的程序员水平会差别很大.我写这篇文章 ...
- 做10年Windows程序员与做10年Linux程序员的区别
如果一个程序员从来没有在linux,unix下开发过程序,一直在windows下面开发程序, 同样是工作10年, 大部分情况下与在linux,unix下面开发10年的程序员水平会差别很大.我写这篇文章 ...
随机推荐
- BZOJ 1030 文本生成器
很老的题目了,很早以前学AC自动机的时候就A过一次 今天算是复习啦 我们可以把问题转化成一个给定字符串都没出现的字符串有多少个 我们建立AC自动机,设dp[i][j]表示走了i步当前在j节点上 在DP ...
- Google Code Style
Google开源项目的代码遵循的规范,见这,C++, OC. PS: vim的配色编辑用户主目录下的.vimrc即可.
- RedMine项目管理系统安装问题(Windows版一键安装包)
安装准备: 操作环境:VMware10 下安装的windows10 系统 使用软件:<bitnami-redmine---windows-installer.exe> 问题描述: 安装过程 ...
- Armitage主屏幕说明与命令行启动
(1)我们将Armitage主屏幕标注为A.B和C A:该区域显示预配置的模块.您可以在模块列表下面的文本框中输入要查找的模块进行查找. B:该区域显示我们可以进行漏洞测试的活跃主机. C:该区域显示 ...
- android下升级软件介绍
编译android: 生成:system.img,ramdisk.img,userdata.img映像文件. ramdisk.img是emulator的文件系统 system.img包括了主要的包.库 ...
- VPN column: PPTP(1)--connecting process
hu_hit原创,如需转载请注明出处.Thanks. 在未来几天会总结一下PPTP的工作过程,分为以下3篇讲述. 1. PPTP连接过程: 2. PPTP协议解析: 3. PPTP的路由. 由于我是工 ...
- notepad++ 编辑器链接地址可点击
很久没用notepad++编辑器,最近因为 sublime 的编码问题,因此用了下 notepad++ .结果发现里面的链接都可以点击,一点都不要编辑,如下图: 那如何把这个功能去掉呢? 我们选择 菜 ...
- mysql 读取硬盘数据
innodb 的最小管理单位是页 innodb的最小申请单位是区,一个区 1M,内含64个页,每个页16K ,即 64*16K=1M, 考虑到硬盘局部性,每次读取4个区,即读4M的数据加载至内存 线性 ...
- apache开源项目-- OODT
Apache OODT (Object Oriented Data Technology) OODT 面向对象的数据技术,开发和促进科学数据管理和归档制度,使跨学科和天体物理学之间的互操作性,行星和空 ...
- 在cshtml页面中,以‘@’开始的表达式 表示C#语句,会被编译执行
在原始的Index.html中是正常显示的,然而在现在这个源代码是个cshtml页面: 但是在cshtml页面中,以‘@’开始的表达式 表示C#语句,会被编译执行,会去寻找controller传度给@ ...