一程序, 使用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]来占位。