登录社区:用户名: 密码: 忘记密码 网页功能:加入收藏 设为首页 网站搜索  

文档

下载

图书

论坛

安全

源码

硬件

游戏
首页 信息 空间 VB VC Delphi Java Flash 补丁 控件 安全 黑客 电子书 笔记本 手机 MP3 杀毒 QQ群 产品库 分类信息 编程网站
  立华软件园 - 安全技术中心 - 技术文档 - 入门基础 技术文章 | 相关下载 | 电子图书 | 攻防录像 | 安全网站 | 在线论坛 | QQ群组 | 搜索   
 安全技术技术文档
  · 安全配制
  · 工具介绍
  · 黑客教学
  · 防火墙
  · 漏洞分析
  · 破解专题
  · 黑客编程
  · 入侵检测
 安全技术工具下载
  · 扫描工具
  · 攻击程序
  · 后门木马
  · 拒绝服务
  · 口令破解
  · 代理程序
  · 防火墙
  · 加密解密
  · 入侵检测
  · 攻防演示
 安全技术论坛
  · 安全配制
  · 工具介绍
  · 防火墙
  · 黑客入侵
  · 漏洞检测
  · 破解方法
 其他安全技术资源
  · 攻防演示动画
  · 电子图书
  · QQ群组讨论区
  · 其他网站资源
最新招聘信息

C语言基本功教程系列(4) - 高效无错的内存访问
发表日期:2007-03-28作者:[转贴] 出处:  

 大家周末好,希望一个星期的学习和工作没能把大家累垮,这样又可以在这里听Aear在这里讲废话了。这个周末的主题就是内存访问,主要是谈谈写程序时候关于使用内存的技巧,以及一些应该注意的地方。

================分割线==================

首先说说动态内存分配。在c语言里用的最多的是malloc和free,在c++则是new new[] delete 和delete[]. 这几个函数是动态内存分配的基础,最常用但也是最占用CPU资源的系统调用之一.而且在大量使用以后很容易造成内存的碎片。如果系统内存中的碎片太多,就会在分配大块内存的时候失败或者只能在虚拟内存上分配内存,这就是为什么有些程序在运行了2,3个小时以后很容易速度不稳定和容易崩溃的原因。另外一个重要的因素就是程序员在写程序的时候,经常会分配了内存而忘记释放。特别是写超过 10W行代码的时候往往忘记了在哪里分配了内存. 所以内存的管理对于游戏的稳定性是非常重要的问题,毕竟大家都是动不动玩上10个小时不休息的主。

目前比较流行的解决方法就是在系统提供的内存分配函数上面,写自己的内存管理函数。在C语言里重写malloc和free,对每个内存的分配和使用情况做跟踪记录。在C++里则是重载操作符 new和delete. 通过提供自己的库,可以很容易检测到memory leakage. 通过在程序开始的时候从操作系统分配到一块足够大的内存,在此基础上进行内存管理,还可以有效的防止内存泄漏,并且还可以支持对象复用技术,提高游戏的速度和稳定性。当然,你也可以使用一些memory leakage的检测工具来检查内存使用情况(比如  firefox memory leakage detection tool 或者 Visual leak detector)。

实际上,在游戏程序设计中,很少使用动态的内存分配,大部分的内存都是事先分配好的。即使是链表或者是树这一类的数据结构,也是用数组进行有效的模拟。

================分割线==================

下面说点代码里边应该注意的问题。在相关内存相关的注意事项中,排在第一位的是内存对齐问题。也就是说,一块内存的首地址,必须要能被2,4,8,16,32 或者64整除。 不同的CPU对于这个数字有不同的需要。

针对Intel最新发布的 Pentium Dual Core系列 Xenon系列,以及早些日子的 Pentium 4系列。推荐使用64 Bytes 或者 128 Bytes的内存对齐。 因为在Pentium4 系列用,每当程序要进行内存访问的时候,CPU的一个预处理模块(Prefetch)会事先把内存中的数据读到Level1 cache中,并且每次读入的数据量是 64个 bytes(Pentium Xenon系列是 128 bytes)。 如果没有进行内存对齐, 比如一个int占用4字节,第一个字节在前64bytes中,后3个字节在后64bytes中,那么 CPU在读取这个int的时候就需要多从内存中拿一次数据, 会大大增加代码的运行时间。让我们看下例子:

__declspec(align(64)) int test[128];       // 64字节对齐

int * pInt = (int *)((char *)test + 1);     // 没有对齐的指针
int * pInt2 = test;                               // 对齐的指针

int f1(void)
{
int i, k=0; 
for(i = 0; i < 16; i++) k+=pInt[i];
return k;
}

int f2(void)
{
int i, k=0;
for(i = 0; i < 16; i++) k+=pInt2[i];
return k;
}

对照附件中的 VTune的测试结果(见附件1),我们可以看出非64bytes对齐的运行时间(clockticks值),几乎是对齐内存的运行时间的3 倍。所以在使用动态或者静态内存的时候,最好注意内存的字对齐问题。在Visual Studio .Net中,可以用 __declspec (align(64))对静态变量,数组或者结构进行内存对齐。动态内存分配可以使用_aligned_malloc() 和  _aligned_free().

这些内存对齐的问题,当前的编译器一般都会帮你优化,但是如果要写自己的内存管理函数,就需要分外注意了。


================分割线==================
下面说一下结构数组问题。经常我们会用到结构数组,形式如下:

struct MyStructure{
    int FirstNumber;
    int SecondNumber;
    int ThiredNumber;
    int FourthNumber;
}  StructureArray[100];

这种类型的数据结构,还有另外一种组织的方式,那就是数组结构,形式如下:

struct MyStructure{
    int FirstNumber[100];
    int SecondNumber[100];
    int ThridNumber[100];
    int FourthNumber[100];
} ArrayStructure;

至于这两种形式用哪种好,要根据具体情况来判断。一般来说,如果要对所有结构中的同一个成员进行连续的访问,比如要求100个结构中所有FirstNumber的和,使用第2种形式会快很多。如果要分别求出每个结构所有成员的和,第一种形式要快很多。 

===========求所有结构第一个成员的和==========
// 错误的选择
for(i = 0; i < 100; i++) Sum += StructureArray[i].FirstNumber;
// 正确的选择
for(i = 0; i < 100; i++) Sum += ArrayStructure.FirstNumber[i];

============求每个结构所有成员的和===========
// 错误的选择
for(i = 0; i < 100; i++) 
    Sum =    ArrayStructure.FirstNumber[i] 
              + ArrayStructure.SecondNumber[i]
              + ArrayStructure.ThirdNumber[i]
              + ArrayStructure.FourthNumber[i];
  
// 正确的选择
for(i = 0; i < 100; i++) 
    Sum =    StructureArray[i].FirstNumber
              + StructureArray[i].SecondNumber
              + StructureArray[i].ThirdNumber
              + StructureArray[i].FourthNumber;

我想道理不用多说大家也明白了吧, 具体到程序设计中要根据哪种操作用的多来决定数据的组织方式。

关于内存访问,还有很多很多需要注意的事项,比如aliasing问题,store forward问题等等,建议大家去参考intel关于pentium的文档.


我来说两句】 【发送给朋友】 【加入收藏】 【返加顶部】 【打印本页】 【关闭窗口
中搜索 C语言基本功教程系列(4) - 高效无错的内存访问

 ■ [欢迎对本文发表评论]
用  户:  匿名发出:
您要为您所发的言论的后果负责,故请各位遵纪守法并注意语言文明。

最新招聘信息

关于我们 / 合作推广 / 给我留言 / 版权举报 / 意见建议 / 广告投放 / 友情链接  
Copyright ©2001-2006 Lihuasoft.net webmaster(at)lihuasoft.net
网站编程QQ群   京ICP备05001064号 页面生成时间:0.00193