免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2647 | 回复: 7
打印 上一主题 下一主题

[C++] 求问SGI STL中allocator的问题,有关内存释放 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2013-01-26 02:47 |只看该作者 |倒序浏览
本帖最后由 Frahm 于 2013-01-26 02:48 编辑

我在看到侯捷的那本《STL 源码剖析》中allocator一章节,对它的实现思路基本了解了,也就是分两级,我主要对第二级,也就是默认的那个allocator的实现有些疑问,
大概说来它是这样的:对于较小的内存分配请求,采用预分配的链表的形式,以8的倍数大小为单位的内存区块(8,16,24,...128 ),每种大小都是一个链表,然后用一个数组把这些链表的头结点存起来,请求内存小于128bytes时就从数组找到对应的链表节点,如果该组链表结点不足,就从一个内部的heap划分出来20块请求大小的内存,加到链表中,再从链表取走一块用,当heap不够20块时,就直接分出去1块用,当一块都不够时(这个时候剩的大小一定也是8的倍数),就把零头全加入到合适大小的链表中去,然后malloc 大小为40块请求大小的内存,20块再和刚刚同样处理(加入合适的链表,分出去一块), 其余20块大小的chunk就留在heap里备用,问题就是他是怎么释放掉malloc的内存的,我只看到malloc了,第二级allocator的代码里没有看到free的字眼,其中的deallocate函数是这样的:
  1. static void deallocate(void *p, size_t n)
  2. {
  3.     obj *q = (obj*)p;
  4.     obj * volatile * my_free_list;
  5.     //大于 128 就呼叫第一级配置器
  6.     if(n  > (size_t) __MAX_BYTES) {
  7.         malloc_alloc::deallocate(p, n);
  8.         return;
  9.     }
  10.     //  寻找对应的free list
  11.     my_free_list = free_list + FREELIST_INDEX(n);
  12.     //调整free list 回收区块
  13.     q -> free_list_link = *my_free_list;
  14.     *my_free_list = q;
  15. }
复制代码
上面的那个malloc_alloc就是第一级allocator, 是针对较大内存分配时才使用的,所以对于在第二级自身malloc的内存,这个函数只是简单的把那块内存返还到了指定大小的链表中而已。
我感觉虽然不该在这里释放,但也总要释放的吧?是我看漏了哪里吗?难道sgi stl的实现中有另一个函数来做这种工作?
如果没有的话,针对这种情形应该如何释放呢?
所有的链表中的内存块都不是独立malloc的,而是一次malloc中的一部分,而且一次malloc的内存很可能分散在多组链表里,我现在想的,是用一个数据结构把每次malloc的内存块的指针保存下来,在最后的最后全部free掉,但是这样又比较危险,如果有对象正在使用这块内存。
是否是这种设计本身决定了不能随便释放内存呢,有没有其他方法可以比较灵活的紧缩/释放allocator占用的内存呢?

论坛徽章:
14
巨蟹座
日期:2013-11-19 14:09:4615-16赛季CBA联赛之青岛
日期:2016-07-05 12:36:0515-16赛季CBA联赛之广东
日期:2016-06-29 11:45:542015亚冠之全北现代
日期:2015-07-22 08:09:472015年辞旧岁徽章
日期:2015-03-03 16:54:15巨蟹座
日期:2014-12-29 08:22:29射手座
日期:2014-12-05 08:20:39狮子座
日期:2014-11-05 12:33:52寅虎
日期:2014-08-13 09:01:31巳蛇
日期:2014-06-16 16:29:52技术图书徽章
日期:2014-04-15 08:44:01天蝎座
日期:2014-03-11 13:06:45
2 [报告]
发表于 2013-01-26 09:22 |只看该作者
程序退出时释放

论坛徽章:
0
3 [报告]
发表于 2013-01-26 23:27 |只看该作者
bruceteen 发表于 2013-01-26 09:22
程序退出时释放

总感觉这样不太合适吧,毕竟stl是一个独立的库,它自己并不知道何时程序退出,我感觉不会是要每次写程序都在最后手动释放的。会不会是他考虑到程序退出后os会回收堆,才没有手动释放呢?总感觉这样比较危险

论坛徽章:
44
15-16赛季CBA联赛之浙江
日期:2021-10-11 02:03:59程序设计版块每日发帖之星
日期:2016-07-02 06:20:0015-16赛季CBA联赛之新疆
日期:2016-04-25 10:55:452016科比退役纪念章
日期:2016-04-23 00:51:2315-16赛季CBA联赛之山东
日期:2016-04-17 12:00:2815-16赛季CBA联赛之福建
日期:2016-04-12 15:21:2915-16赛季CBA联赛之辽宁
日期:2016-03-24 21:38:2715-16赛季CBA联赛之福建
日期:2016-03-18 12:13:4015-16赛季CBA联赛之佛山
日期:2016-02-05 00:55:2015-16赛季CBA联赛之佛山
日期:2016-02-04 21:11:3615-16赛季CBA联赛之天津
日期:2016-11-02 00:33:1215-16赛季CBA联赛之浙江
日期:2017-01-13 01:31:49
4 [报告]
发表于 2013-01-26 23:54 |只看该作者
没仔细看过SGI STL的源代码,不过我估计它真的有可能不把内存还给OS,一直等到进程退出。
采取这种策略的内存管理库还有TCMalloc,也是只借不还的。
这种策略有一定合理性,因为一个使用了很多内存的程序很有可能继续使用很多内存,如果内存管理库过早的把内存还给了OS,下次需要内存的时候还要向OS申请,而这是一个很贵的操作。
当然对于内存使用起伏很大的程序来说这不一定是个好策略,尤其是当总物理内存不太充裕的时候。

论坛徽章:
1
技术图书徽章
日期:2014-03-06 15:32:30
5 [报告]
发表于 2013-01-27 00:32 |只看该作者
注释不是写的很清楚么,呼叫第一级配置器

论坛徽章:
0
6 [报告]
发表于 2013-01-27 00:38 |只看该作者
windoze 发表于 2013-01-26 23:54
没仔细看过SGI STL的源代码,不过我估计它真的有可能不把内存还给OS,一直等到进程退出。
采取这种策略的内 ...

嗯,我想了下,打算稳妥点,用一个数组保存每次malloc的内存指针(非动态分配,否则调用自身会出问题),再用一个int累加malloc的总大小,在结束前,各容器先都deallocate,在allocator内部计算一下链表中总大小,加上heap中剩余大小,核对是否与之前存的分配的大小相等,相等的话,就一并释放,否则说明释放有问题,再调整。
多谢二位回答我的问题。

论坛徽章:
0
7 [报告]
发表于 2013-01-27 00:41 |只看该作者
selfrun 发表于 2013-01-27 00:32
注释不是写的很清楚么,呼叫第一级配置器

那个是针对大于128bytes的情况,alloc的时候也是大于128才用第一级malloc,这个调用并不适用<128bytes的情况,而第二级就是为了高效处理小内存分配的设立的。

论坛徽章:
4
水瓶座
日期:2013-09-06 12:27:30摩羯座
日期:2013-09-28 14:07:46处女座
日期:2013-10-24 14:25:01酉鸡
日期:2014-04-07 11:54:15
8 [报告]
发表于 2013-01-27 11:54 |只看该作者
STL的内存池是伴随程序生命期的.
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP