保持C/C++程序代码的可伸缩性
日期:2007年5月2日 作者: 查看:[大字体 中字体 小字体]-
在今天,已有许多的32位应用程序感到,在32位平台上可用的虚拟内存受到了一定的限制,对程序开发者来说,即使是开始关注64位平台时,也不得不维护软件的32位版本,这就需要一种方法,以使代码的两个版本都保持相当的可伸缩性。
目前的内存剖析工具能帮助确定,当程序达到峰值内存使用量时,都发生了什么,但是这些工具都过于关注已分配的内存块,而不是已提交的虚拟内存地址空间,而这两种衡量标准没有直接的相关性,如内存泄漏、内存碎片、内存块内的空间浪费、或过度延迟的内存单元重新分配这些因素,都会导致不必要的虚拟内存提交。运行时分析工具如IBM Rational Purify或Parasoft Inuse均可以提供内存泄漏及已用内存的描述,这些信息是非常有用的,但是,一个特殊的内存块也许可能、也许不可能影响到虚拟内存覆盖区,另外,甚至一个有碎片的内存堆中的一个小块,也能直接影响到虚拟内存覆盖区。从另一方面来说,在此范围内的任意内存块--甚至泄漏的块,对虚拟内存覆盖区来说,也不会与之有什么关系,除非每一个此范围内有用的内存块能重新分配到一个更紧凑的范围内,这就有点像Java或托管程序的垃圾回收机制,但对大多数C/C++本地应用程序来说,就绝对不可能了,因为在虚拟内存空间中,它们内存块的位置是不确定的。
至于本地代码,不必要的虚拟内存使用,这个实际的问题,比未清理的内存块这个理论上的问题,更加有实质性。未清理的内存块可能导致虚拟内存的浪费,造成过多的系统开销,但或者不会;这完全依赖于堆管理器是否提交了更多的虚拟内存,以支撑这种浪费。某些很小的未使用的内存块,不会引起不必要的堆"扩展"。与其让你来猜哪一个或多少已浪费的内存块导致了堆扩展,倒不如学会怎样判定出有意义的浪费是什么。当堆中包含不再使用的内存块时,此时通过加入对未缩减堆的检查,就能确定出与你的程序虚拟内存要求有很大关系的、必须进行的内存块清理。
为找出哪一个堆中的内存块需多留意,必须在程序中加入一些额外的代码,以跟踪内存堆范围及已分配的内存块。对额外的代码进行条件编译,生成一个特定的版本,也许是一个不错的办法。
为达到此目的,需编写自定义的内存分配例程,并跟踪每一个内存块,另有一个自定义的释放例程,且跟踪虚拟内存中堆的位置,请参见例1与例2的伪代码算法。可能还需编写自定义的访问函数以标记出访问过的内存块,以便于在适当的时候释放虚拟内存,所有这些并不需要过多的内存开销。另一方面,如果你的程序以堆的形式使用了大量的内存,那么将会极大地降低性能,此处的方法也不是长久之计。
例1:
/* 输入参数*/
ADDRESS triggerAddr
SIZE triggerSize
LIST a list of tracked heap ranges
IF (the virtual memory at triggerAddr is tracked on the list as part of a heap range)
DO
IF (triggerAddr + triggerSize >
(the tracked upper boundary of that heap range))
DO
/* 一个现有的堆范围被扩展 */
make system call(s) to determine the base and extent of the newly committed range that contains the addresses from triggerAddr to (triggerAddr + triggerSize)
update the size of the tracked heap range to indicate its new upper limit
END
END
ELSE DO
/* 在triggerAddr中有一个新的堆范围 */
make system call(s) to determine the base and extent of the newly committed range that contains the addresses from triggerAddr to (triggerAddr + triggerSize)
track the new committed range in the list of heap ranges
END
例2:
/* 输入参数 */
ADDRESS triggerAddr
SIZE triggerSize
LIST a list of tracked heap ranges
/* 局部变量 */
ADDRESS origRangeBase
SIZE origRangeSize
BOOL bFoundChange
bFoundChange = FALSE
IF (the virtual memory at triggerAddr is not tracked on the heap range list as part of a heap range)
DO
/*似乎我们已经清楚此次释放了。*/
END
ELSE IF (an access exception occurs when memory at triggerAddr is read)
DO
bFoundChange = TRUE
END
IF (bFoundChange) DO
/*因为之前内存块占用的空间被释放了,所以堆占用的虚拟内存范围就改变了。*/
make system calls to determine the bases and extents of the tracked committed heap ranges in the immediate vicinity of the decommitted range that includes the addresses from triggerAddr to (triggerAddr + triggerSize)
/*更新堆范围跟踪,以反映剩余提交的范围 */
IF (any portion of the tracked heap range that contained the block at TriggerAddr is still committed)
DO
update the heap range list to track just the portion(s) of that range that remain committed
END
ELSE
DO
delete the list element that tracks the range
END
END QQread.com 推出Windows2003教程 win2003安装介绍 win2003网络优化 win2003使用技巧 win2003系统故障 服务器配置 专家答疑 - [1] [2] [3] 下一页
-
- 保持C/C++程序代码的可伸缩性 相关文章:
- ·保持C/C++程序代码的可伸缩性
- 保持C/C++程序代码的可伸缩性 相关软件
- 特别声明:本站除部分特别声明禁止转载的专稿外的其他文章可以自由转载,但请务必注明出处和原始作
- 者.文章版权归文章原始作者所有.对于被本站转载文章的个人和网站,我们表示深深的谢意。如果本站转
- 载的文章有版权问题请联系编辑人员,我们尽快予以更正. 转载请注明来源:http://www.hackhome.com
下一篇:VC编程轻松获取局域网连接通知
精品推荐
热点TOP10
- ·用c#监控网络流量
- ·C#编写的windows计算器-源代码
- ·C #中的几个线程同步对象方法
- ·飞机订票系统设计
- ·C/C++笔试、面试题目大汇总
- ·《俄罗斯方块》程序编写详解
- ·Windows API-GDI入门基础知识详解(2)
- ·socket编程原理
- ·打字游戏
- ·七年IT奋斗纪实及感悟
- ·无废话C#设计模式之九:Proxy
- ·牛顿和拉格朗日插值算法
- ·VC++动态链接库编程之MFC扩展 DLL
- ·C# 操作文件
- ·如何用C#编写文本编辑器
- ·c#操作word表格
- ·编程特例篇——LOGO语言
- ·Raw Socket(原始套接字)实现Sniffer(嗅探)
- ·C#实现窗口最小化到系统托盘
- ·C# 学习使用ErrorProvider
特别推荐
- ·C#程序开发中的常用函数汇总
- ·C#数据库操作的三种经典用法
- ·C/C++笔试、面试题目大汇总
- ·Beej的网络socket编程指南
- ·socket编程原理
- ·C语言的常用库函数使用方法分析及用途
- ·在C语言中如何处理时间和日期
- ·C++设计模式之Singleton
- ·VC++动态链接库编程之MFC扩展 DLL
- ·TCP/IP网络重复型服务器通信软件的设计
- ·DirectX游戏开发入门
- ·经典与现代的结合:在MFC中集成RAD .NET框架
- ·Windows API-GDI入门基础知识详解(2)
- ·Visual C++ 入门精解
- ·C#基础概念二十五问
- ·用C#实现pdf文件的完整性验证
- ·成为嵌入式程序员应知道的0x10个问题
- ·TCP/IP编程实现远程文件传输
- ·几个C#编程的小技巧
- ·C# 编码规范和编程好习惯
