对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++编程]”的内容,如果你对以上该文章内容感兴趣,你可以看看七道奇为您推荐以下文章:
本文地址: | 与您的QQ/BBS好友分享! |