有感于STL的内存管理

上传人:m**** 文档编号:457445558 上传时间:2022-09-04 格式:DOCX 页数:14 大小:19.44KB
返回 下载 相关 举报
有感于STL的内存管理_第1页
第1页 / 共14页
有感于STL的内存管理_第2页
第2页 / 共14页
有感于STL的内存管理_第3页
第3页 / 共14页
有感于STL的内存管理_第4页
第4页 / 共14页
有感于STL的内存管理_第5页
第5页 / 共14页
点击查看更多>>
资源描述

《有感于STL的内存管理》由会员分享,可在线阅读,更多相关《有感于STL的内存管理(14页珍藏版)》请在金锄头文库上搜索。

1、有感于 STL的内存1. 背景前些天在一个技术分享会上,某大牛说,STL使用了内存池,释放内存的时候,并不释放 给OS,而是自己由留着用。听到这些观点后,我就有些着急了,因为我以前一直是直接使用STL的一些工具类的,比 如std:string、std:map、std:vector、std:list等等,从来都没有关注过内存的问题。带着内存的问题,我花了两三天的时间去阅读STL的代码,并且写一些简单的程序进行测 试;下面列举一些心得体会,但是却没有什么大的结论-.-2. 容易误解的简单例子我们以STL中的map为例,下面有一个使用map的简单例子,大部分人可以在30秒内写 好。void test

2、map()mapint, floattestmap;for (i nt i = 0; i 1000000; i+) testmapi = (float)i;testmap.clear();为了在调用map:clear()之后查看进程的内存使用量,我们可以加几行代码让程序暂停一下。void testmap()mapint, floattestmap;for (i nt i = 0; i 1000000; i+) testmapi = (float)i;testmap.clear();/观察点int tmp; cout tmp; 编译运行上面的程序,你会看见这样的情况:ps显示进程的内存使用量为4

3、0MB多。这时, 你会毫不犹豫地说,STL的map使用了内存池(memory pool)。然后,我就跑去阅读libstdc+的STL的源代码,STL提供了很多种Allocator的实现,有基 于内存池的,但是默认的std:allocator的实现是new_allocator,这个实现只是简单的对new 和delete进行了简单的封装,并没有使用内存池。这样,怀疑的对象就转移到glibc的malloc 函数了。malloc提供的两个函数来查看当前申请的内存的状态,分别是malloc_stats()和 mallinfo(),它们都定义在vmalloc.h里。为了弄清楚这个问题,我们对上面的例子进行

4、如下的改造:#i nclude vmalloc.hvoid testmap()malloc_stats(); / testmap;for (i nt i = 0; i v 1000000; i+) testmapi = (float)i;malloc_stats(); / =观察点 2 testmap.clear();malloc_stats(); / =观察点 3 这个例子的运行环境是这样的:den gmwmy $ g+ -vReading specs from /usr/lib/gcc/x86_64-redhat-linux/346/specsCon figured with:./c on

5、 figure-prefix=/usr-ma ndir=/usr/share/ma n-i nf odir=/usr/share/info -e nable-shared -e nable-threads=posix -disable-check ing -with-system-zlib-enable-_cxa_atexit-disable-lib un wi nd-exceptio ns-en able-java-awt=gtk -host=x86_64-redhat-l inuxThread model: posixgcc version 3.4.6 20060404 (Red Hat

6、346-9)程序的运行结果是这样的: 在观察点1:* system bytes = 0* in use bytes = 0在观察点2:* system bytes = 48144384* in use bytes = 48005120 在观察点3:system bytes = 48140288 in clude/bits/allocator.h - in clude/i386-redhat-li nu x/bits/c+allocator.h - include/ext/new_allocator.h(即是说,std:allocator =_gnu _cxx: new_allocator)根据

7、C+的标准,STL的allocator,把对象的申请和释放分成了4步:第1步:申请内存空间,对应函数是allocator:allocate() 第2步:执行构造函数,对应函数是allocator:co nstruct() 第3步:执行析构函数,对应函数是allocator:destroy() 第4步:释放内存空间,对应函数是allocator:deallocate() STL崇尚拷贝,你往容器里放东西或者从容器里取东西,都是要调用拷贝构造函数 的。比如,你有一个对象a要插入到map里,过程是这样的:map先申请一个结点的空间调用拷贝构造函数初始化该结点 把新结点插入到map的红黑树中STL中实

8、现了好多种不同的更为具体的allocator,如下(GNU GCC关于Memory的官 方文档):_gnu_cxx:new_allocator:简单地封装了 new和 delete操作符,通常就是std:allocator _gnu_cxx:malloc_allocator:简单地封装了 malloc 和 free 函数 _gnu_cxx:array_allocator:申请一堆内存 _gnu_cxx:debug_allocator:用于 debug _gnu_cxx:throw_allocator:用于异常 _gnu_cxx:_pool_alloc:基于内存池 _gnu_cxx:_mt_al

9、loc:对多线程环境进行了优化 _gnu _cxx:bitmap_allocator: keep track of the used and unu sed memory locati ons.上面的8个 allocator 的实现中,bitmap_allocator、pool_allocator 和_mt_alloc 是基于 cache 的,其它的不基于cache*那么?如何指定使用一个特殊的allocator呢?示例如下:/方法1/方法2map a1;map in t, in t, less, std:allocatorpair a3;/方法3,方法1、方法2、方法3都是等价的mapv i

10、n t, i nt, lessv in t, _gnu _cxx: new_allocatorvpairvi nt, i nt a2;/方法4,使用了基于cache的allocator mapvint, int, lessvint, _gnu_cxx:_pool_allocpair a4;5.内存碎片是容易被忽视的导致OutOfMemory的 原因这个观点有点类似于磁盘碎片,也可以称为内存碎片吧,当内存碎片过多的时候,极容易出现OutOfMemory错误;使用STL的map特别容易出现这种情况,往map里插入了海量的小对象,然后释放了 一些,然后再想申请内存时,就出现OutOfMemory错误

11、了;这种现象不只是在使用STL的情况会发现,下面举一个例子来说明内存碎片的问题,尽 管这个例子没有使用STL。举例之前,先说明一下这个例子中使用的两个查看当前进程的内存统计量的2个函数:int get_max_malloc_length_inMB():得到当前可以申请的最长的内存长度(MB);这个 函数不停地调用p=malloc(length*1O24*1O24);如果成功,贝则length+,并且free(p); 如果失败,返回(le ngth-1)。 int get_free_memnKB():得到当前可以申请的内存总量(KB);这个函数不停地调如果失败,则把所有的1KB内存释放,再返回c

12、ount。为了测试方便,我在运行程序前,设置了进程的最大内存为200MB,使用的命令如下:ulimit -m 204800;ulimit -v 204800;这个例子把申请到的内存以矩阵的形式存储起来,先按列优先把指针存起来,再按行优先进行free,这样会造成大量的内存碎片;例子的伪代码如下:typedef char* PtrType;PtrType * Ptrs = (PtrType*) malloc( ROW * sizeof(PtrType*);/第1步:占领所有的内存,按列优先进行申请for(j=0; jvCOL; +j) for(i=0; iROW; +i) Ptrsji = malloc(1024);/第2步:按行优先释放所有的内存,

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 办公文档 > 解决方案

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号