现在的位置: 首页 > 综合 > 正文

内存碎片

2013年03月13日 ⁄ 综合 ⁄ 共 1120字 ⁄ 字号 评论关闭

一程序, 使用stl容器保存大量数据

 

top/pmap看, 进程的writtable/private空间很大, 明显不合理;

 

使用malloc_stats 看, in use的内存正常。

 

那么唯一合理的解释是:

1 内存碎片

2 进程调用了free时, 并没有向OS归还内存; free内部有缓存机制以便下次malloc

3 和stl容器无关

 

 

通常所谓的stl的allocator分配器, 其内部缓存, 通常是应用层的缓存: clear掉容器内所有对象时, 只是把内存还给了allocator; allocator的生命周期结束时, 肯定会调用free之类的操作向OS归还内存。

 

至于最终是否归还, 就是malloc/free自己的事情了。 目前来看malloc/free肯定有缓存机制

 

 

 

 

 

 

 

 

推荐一个tcallocator, 可以不用修改代码, 只连接一个库就能使用。 见code.google

 

 

 

 

=========

记一下解决这个问题时的思路过程。。

1 怀疑stl容器本身没释放

2 怀疑stl的allocator没释放

3 怀疑其他地方漏掉free之类的

4 内存碎片

==其中第2个是不用考虑的, 特别是在使用默认的allocator时

 

 

 

 

 

 

 

==========

从一篇帖子上看到, 从效率角度上说, 自实现的多线程情况下使用mutex的allocator, 还不如直接new/delete。

大概时间: malloc 花掉500 nanosecond, 而一次加锁过程需要2000 nano

 

此次没实际验证; 但是从我个人之前的一次项目过程中得到佐证。 2年前自己写过一个多线程+mutex的allocator, 启动加载大量数据时, 确实比直接new慢许多

 

 

 

 

 

 

 

==========

一种避免内存碎片的小技巧

typedef struct _NODE

{

    char *pData;

    int nLength;

} Node;

使用的时候:

Node *pNode = (Node*)malloc(sizeof(Node));

pNode->Data = (char*)malloc(pNode->nLength);

这样是没有任何问题的,但是却有内存碎片的产生;

 

解决办法:

typedef struct _Node

{

   int nLength;

    char pData[1];

} Node;

具体的使用方法:

int nDataLength = (nLenght == 0 ? 1 : nLength) - 1;

Node *pNode = (Node*)malloc(sizeof(Node) + nDataLength);

这样就避免了内存碎片的问题。

 

另外上面又有一个小技巧就是对齐问题:

由于C语言中编译器是四字节对齐的,所以上面需要加上nPedding[3]来占位。

抱歉!评论已关闭.