荔园在线

荔园之美,在春之萌芽,在夏之绽放,在秋之收获,在冬之沉淀

[回到开始] [上一篇][下一篇]


发信人: oopilix ([0;1;32;40m), 信区: Visual
标  题: [zz]Windows内存机制解析(二)
发信站: 荔园晨风BBS站 (Mon Oct 13 23:03:57 2003), 站内信件

leezy_2000(原作)     by leezy_2000

                           2003-10-8 17:01

三、浅谈一下Heap

(鉴于Matt Pietrek在它的《Windows 95 系统程式设计大奥秘》对9x系统的heap做
了非常详细的讲解,此处涉及的内容将仅限于Win2000)



Heap与Stack正好相反,你需要手动来管理每一块内存的申请和释放(在没有垃圾
收集机制的情况下),而对于C/C++程序员来说,操作Heap的方式实在是太多了点
。下面是几乎所有可以操作堆内存的方法的列表:

malloc/free

new/delete

GlobalAlloc/GlobalFree

LocalAlloc/LocalFree

HeapAlloc/HeapFree



其中malloc/free由运行时库提供,new/delete为C++内置的操作符。他们都使用运
行时库的自己的堆。运行时库的在2000和win9x下都有自己独立的堆。这也就意味
着只要你一启动进程,你将至少有两个堆,一个作为进程缺省,一个给C/C++运行
时库。



GlobalAlloc/GlobalFree和LocalAlloc/LocalFree现在已失去原有的含义,统统从
进程缺省堆中分配内存。



HeapAlloc/HeapFree则从指定的堆中分配内存。



单就分配内存而言(new/delete还要管构造和析构),所有这些方式最终要归结到
一点2000和98下都是是HeapAlloc。所以微软才会强调GlobalAlloc/GlobalFree和
LocalAlloc/LocalFree会比较慢,推荐使用HeapAlloc,但由于Global**和
Local**具有较简单的使用界面,因此即使在微软所提供的源代码中他们仍被大量
使用。必须指出的是HeapAlloc并不在kernel32.dll中拥有自己的实现,而是把所
有调用转发到ntdll.RtlAllocateHeap。下面这张从msdn中截取的图(图2),应该
有助于我们理解同堆相关的API。



堆内部的运作同SGI STL的分配器有些类似,大体上是这样,OS为每个堆维护几个
链表,每个链表上存放指定大小范围的区块。当你分配内存时,操作系统根据你所
提供的尺寸,先确定从那个链表中进行分配,接下来从那个链表中找到合适的块,
并把其线性地址返还给你。如果你所要求的尺寸,在现存的区块中找不到,那么就
新分配一块较大的内存(使用VirtualAlloc),再对他进行切割,而后向你返还某
一区块的线性地址。这只是一个大致的情形,操作系统总在不停的更新自己的堆算
法,以提高堆操作的速度。

堆本身的信息(包括标志位和链表头等)被存放在Heap Header中,而堆句柄正是
指向Heap Header的指针,Heap Header的结构没有公开,稍后我们将试着做些分析
。非常有趣的是微软一再强调只对toolhelp API有效的HeapID其实就是堆句柄。



原来是准备分析一下堆内部的一些结构的,可后来一想这么做实用价值并不是很大
,所需力气却不小。因此也就没具体进行操作。但这里把实现监测堆中各种变化的
小程序的实现思路公开一下,希望对大家有所帮助。这个小程序非常的简单,主要
完成的任务就是枚举进程内所有的堆的变化情况。由于涉及到比较两个链表的不同
,这里使用了STL的vector容器和某些算法来减少编码。同时为了使STL的内存使用
不对我们要监测的对象产生干扰,我们需要建立自己的分配器,以使用我们单独创
建的堆。此外还需要特别注意的一点是由于toolhelp API Heap32Next在运行过程
中不允许对任何堆进行扰动(否则他总返回TRUE),导致我们只能使用vector,并
预先保留足够的空间。(访问堆内部某些信息的另一种方式是使用HeapWalk API,
看个人喜好了)。



程序的运行过程是这样的,先对当前进程中存在的堆进行枚举,并把结果存入一个
set类型的变量heapid1,接下来创建自己的堆给分配器使用,并对进程中存在的堆
再次进行枚举并把结果存入另一个set类型的变量heapid2,这样就可以调用
set_difference求出我们新建堆的ID,再以后列举队内部的信息时将排除这个ID所
表示的堆。接下来就可以在两点之间分别把堆内部的信息存入相应的vector,比较
这两个vector,就可以得到对应于分配内存操作,堆内部的变化情况了。



http://www.csdn.
net/Develop/ArticleImages/21/21436/CSDN_Dev_Image_2003-10-81710470.gif


下面是一些悬而未决的问题,那位感兴趣可以自己探索。



Heap Header结构是什么样的?



堆内部对内存块的组织方式?(是链表么)



每一个小块的描述信息在那里?(如果是链表,那就应该有指针使这些小块彼此相连
。)


--


 ※ IP来源:·荔园晨风BBS站 bbs.szu.edu.cn·[FROM oo.pi.li.x]
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh

※ 来源:·荔园晨风BBS站 bbs.szu.edu.cn·[FROM: 61.144.235.39]


[回到开始] [上一篇][下一篇]

荔园在线首页 友情链接:深圳大学 深大招生 荔园晨风BBS S-Term软件 网络书店