当前位置:七道奇文章资讯编程技术VC/C++编程
日期:2011-03-22 13:55:00  来源:本站整理

对C++程序内存管理的精雕细琢[VC/C++编程]

赞助商链接



  本文“对C++程序内存管理的精雕细琢[VC/C++编程]”是由七道奇为您精心收集,来源于网络转载,文章版权归文章作者所有,本站不对其观点以及内容做任何评价,请读者自行判断,以下是其具体内容:

利用程序分配内存的办法,对程序的履行性能有着深化的影响.目前,通用的内存分配办法本质上已非常高效,但仍有改良的空间.

内存分配,不可一层不变

本日,对绝大大都程序来说,通用的内存分配办法--此处指代分配算符(Allocator:即malloc或new),已到达了抱负的速度及满意了低碎片率的要求,但是,在内存分配范畴,一丁点的信息都值得探究好久,某些特定程序关于分配情势的信息,将有助于实现专门的分配算符,可明显地提高大大都高性能要求程序的性能底线.有时,当通用内存分配算符平均耗费几百个时钟周期时,一个杰出的自定义内存分配算符大概只需求不到半打的周期.

这就是为什么大大都高性能、高要求的利用程序(如GCC、Apache、Microsoft SQL Server),都有着它们自己的内存分配算符.大概,把这些专门的内存分配算符归纳起来,放进一个库中,是个不错的设法,但是,你的程序大概有差别的分配情势,其需求别的的内存分配算符,那怎么办呢?

等等,还有呢,假如我们计划了一种特别用处的内存分配算符,便可以不断发展下去,由此可从中挑选出一些,来构成一个通用目的的内存分配算符,假如此通用分配算符优于现有的通用分配算符,那么此项计划就是有效及实用的.

下面的示例利用了Emery小组的库--HeapLayers(http://heaplayers.org/),为了定义可配置的分配算符,此中利用了mixins(在C++社区中,也被称为Coplien递归情势):通过参数化的基来定义类,每一层中只定义两个成员函数,malloc和free:

template <class T>
struct Allocator : public T {
 void * malloc(size_t sz);
 void free(void* p);
 //系统相关的值
 enum { Alignment = sizeof(double) };
 //可选接口e
 size_t getSize(const void* p);
};

在每一层的实现中,都有大概向它的基类恳求内存,普通来说,一个不依靠于外界的内存分配算符,城市处在层次的顶层--直接向前恳求系统的new和delete操作符、malloc和free函数.在HeapLayers的术语中,没有顶层堆,以下是示例:

struct MallocHeap {
 void * malloc(size_t sz) {
  return std::malloc(sz);
 }
 void free(void* p) {
  return std::free(p);
 }
};

为获得内存,顶层堆也能通过系统调用来实现,如Unix的sbrk或mmap.getSize函数的情形就对比特别,不是每个人都需求它,定义它只是一个可选项.但假如定义了它,你所需做的只是插入一个存储内存块大小的层,并供应getSize函数,见例1:

例1:

template <class SuperHeap>
class SizeHeap {
 union freeObject {
  size_t sz;
  double _dummy; //对齐所需
 };
public:
 void * malloc(const size_t sz) {
  //增添必要的空间
  freeObject * ptr = (freeObject *)SuperHeap::malloc(sz + sizeof(freeObject));
  //存储恳求的大小
  ptr->sz = sz;
  return ptr + 1;
 }
 void free(void * ptr) {
  SuperHeap::free((freeObject *) ptr - 1);
 }
 static size_t getSize (const void * ptr) {
  return ((freeObject *)ptr - 1)->sz;
 }
};

SizeHeap是怎样实现一个实用的层,并挂钩于它基类的malloc与free函数的最好示例,它在完成一些额外的工作之后,把改恰好的后果返回给利用者.SizeHeap为存储内存块大小,分配了额外的内存,再加上得当的当心调整(指union),尽大概地避免了内存数据对齐问题.不难想像,我们可构建一个debug堆,其通过特定情势在内存块之前或之后填充了一些字节,通过查抄能否情势已被保存,来确认内存的溢出.事实上,这恰是HeapLayers的DebugHeap层所做的,非常的简便.

让我们再来看看,以上还不是最抱负的状况,某些系统已经供应了计算已分配内存块大小的原语(此处指操作符,即前述的分配算符),在这些系统上,SizeHeap实际上只会浪费空间.在这种情形下(如Microsoft Visual C++),你将不需求SizeHeap与MallocHeap的衔接,因为MallcoHeap将会实现getSize:

struct MallocHeap {
 ... 与上相同 ...
 size_t getSize(void* p) {
  return _msize(p);
 }
};

但仿佛还有一些不足之处.想一想,我们是在统计时钟周期,假如一个系统的malloc声明了内存的块大小将存储在实际块之前的一个字中,那将会怎样呢?在这种情形下,SizeHeap还是会浪费空间,因为它仍会在紧接着系统已植入的块后存储一个字.此处所需的,只是一个用SizeHeap的办法实现了getSize的层,但未挂钩malloc与free.这就是为什么HeapLayers把前面的SizeHeap分成了两个,见例2:

例2:

template <class Super>
struct UseSizeHeap : public Super {
 static size_t getSize(const void * ptr) {
  return ((freeObject *) ptr - 1)->sz;
 }
protected:
 union freeObject {
  size_t sz;
  double _dummy; //对齐所需
 };
};
template <class SuperHeap>
class SizeHeap: public UseSizeHeap<SuperHeap>{
 typedef typename
 UseSizeHeap<SuperHeap>::freeObject
 freeObject;
public:
 void * malloc(const size_t sz) {
  //增添必要的空间
  freeObject * ptr = (freeObject *)SuperHeap::malloc(sz + sizeof(freeObject));
  //存储恳求的大小
  ptr->sz = sz;
  return (void *) (ptr + 1);
 }
 void free(void * ptr) {
  SuperHeap::free((freeObject *)ptr - 1);
 }
};

目前,SizeHeap就会精确地增添UseSizeHeap层,并操纵它的getSize实现了,而UseSizeHeap也能通过其他配置来利用--这是一个非常文雅的计划.
  以上是“对C++程序内存管理的精雕细琢[VC/C++编程]”的内容,如果你对以上该文章内容感兴趣,你可以看看七道奇为您推荐以下文章:

  • 对Class.getMethod()的调用未经查抄
  • 对C++中引用的增补阐明(实例)
  • 对C++程序内存管理的精雕细琢
  • 关于ASP.NET/C#中对Cookie的操作
  • 本文地址: 与您的QQ/BBS好友分享!
    • 好的评价 如果您觉得此文章好,就请您
        0%(0)
    • 差的评价 如果您觉得此文章差,就请您
        0%(0)

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

       评论摘要(共 0 条,得分 0 分,平均 0 分) 查看完整评论
    Copyright © 2020-2022 www.xiamiku.com. All Rights Reserved .