用户登录  |  用户注册
首 页商业源码原创产品编程论坛
当前位置:PB创新网文章中心编程技巧Visual C++

编程宝典 保持C/C++程序代码可伸缩性

减小字体 增大字体 作者:佚名  来源:本站整理  发布时间:2009-03-16 20:37:24

  跟踪堆内存块

  可使用自定义的内存分配函数来进行内存块的跟踪,而这种函数最初被称为普通内存分配函数,举例来说,C语言程序中一般使用malloc(),尔后,自定义的内存分配会进行以下一系列的操作:

  ·在目前已分配的内存块列表中,跟踪新分配的内存块。

  ·决定是否向系统提交虚拟内存。

  ·如果虚拟内存已被提交,跟踪包含此内存块的堆范围,并更新上述堆内存块列表,以标识出从未被访问过的内存块。

  还需要自定义的释放与重分配内存函数,以便通过程序中使用的内存块的地址与大小,来更新内存块列表。所跟踪的堆内存块列表应包含如下结构:

  ·内存块的基地址。

  ·自身大小

  ·用于指示自从上次虚拟内存被提交之后,内存块是否被访问过的布尔值。

  当一个内存块被释放后,自定义的释放代码将会进行以下操作:

  ·如果自从上次堆扩展之后,内存块还未被访问过,将向程序报告。

  ·从列表中删除跟踪的内存块。

  ·判定系统是否已释放了包含此内存块的虚拟内存。

  ·如果虚拟内存被释放,要相应地更新,以反映剩余的堆范围。

  当一个内存块被重新分配时,你的自定义重新分配内存代码必须进行以下两种操作:首先,在释放之后重新跟踪内存块,因为重新分配的内存块可能不在原位置;其次,在分配之后也要重新跟踪新的基地址及分配内存块的大小。另有一个可选的方法,你可检查是否重新分配的内存块被移动了,如果没有被移动,只需仅仅更新内存块跟踪列表,标出此内存块的大小;如果内存块还在同一基地址,但是增长了,此时就要检查堆扩展,并按照前述分配内存的方法重来一遍。

  跟踪堆自身

  堆跟踪取决于当内存块被分配或释放时,虚拟内存是否分别被提交或释放,依此可以建立一张堆内存范围跟踪表,以确定在程序运行期间,虚拟内存空间中堆的确切位置,跟踪列表中应包括如下数据:

  ·跟踪范围的基地址

  ·自身大小

  在Windows操作系统中,这些值可通过HeapWalk()调用获得,此处要注意的是,HeapWalk()函数调用开销巨大,因此,只在程序需要时调用,而不是当有内存分配或释放时都调用。另一种Windows上的方法是使用IsBadReadPointer()函数,当一个内存块被释放后,你可以调用这个函数快速地判定包含此内存块的虚拟内存是否已被释放。另一个可以跨平台的备选方法是,可试着访问包含此内存块的虚拟内存,并捕捉可能发生的访问异常。此外,只有在一种情况下会考虑使用如HeapWalk()这样开销巨大的函数,就是需判定邻近剩余的已提交堆范围。

  通过一种探测堆内存提交的算法,堆内存跟踪列表会不断地增长,如例1中所示。要注意的是,当你的程序分配一个内存块时,自定义的内存分配代码也能跟踪到这些内存块,并使用例1中的算法来更新包含内存块的堆列表。如果一个内存块的分配导致了额外的虚拟内存被提交,那么被内存块占用的虚拟内存会在之前就释放,或许之前就被用作别的用途。在任一情况中,必须有条件地更新堆范围跟踪列表: l 如果正在跟踪已提交范围的基地址,此时必须更新范围的大小,以指示出新的范围上限。

  ·否则,必须建立一张新的堆内存范围跟踪表。

  如果一个新的内存块出现在一个之前未被跟踪的堆范围中,就满足了以上条件,此时明智地使用前述的系统调用可高效地跟踪堆内存范围。

  当你的程序释放一个内存块时,自定义的内存释放代码会使用到如例2中的算法,此算法会先判定释放的内存是否与被跟踪的堆内存范围有关;接下来,必须检查已释放内存块占用的空间是否仍处于提交状态,如果是,表明了即使内存块被释放,虚拟内存的覆盖区也没有发生改变,否则,你的代码必须进行如例2结尾处的系统调用--如Windows中的HeapWalk()--以确保跟踪的堆是最新的,且包含堆内存块的虚拟内存已被释放。
天极yesky

上一页  [1] [2] [3]  下一页

Tags:

作者:佚名

文章评论评论内容只代表网友观点,与本站立场无关!

   评论摘要(共 0 条,得分 0 分,平均 0 分) 查看完整评论
PB创新网ourmis.com】Copyright © 2000-2009 . All Rights Reserved .
页面执行时间:14,453.13000 毫秒
Email:ourmis@126.com QQ:2322888 蜀ICP备05006790号