内存碎片产生原因及解决方法


1、现象描述

  • 某些应用程序频繁调用 malloc函数申请内存空间,且申请空间的大小差别比较大,使用完成后通过 free函数释放内存空间,但内存空间依然缓存在glibc中,没有归还操作系统,导致系统内存不足。

2、原因分析

内存空间分配

Glibc中进程的内存分配由两个系统调用完成: brk 和 mmap:

  • brk 是将数据段(.data)的最高地址指针 _edata 往高地址推; brk 分配的内存需要等到高地址内存释放以后才能释放
    假设先后通过 brk 申请了A和B两块内存,在B释放之前, A是不可能释放的,仍然被进程占用,通过TOP查看疑似“内存泄露”。
  • mmap 是在进程的虚拟地址空间中申请一块空闲的空间。 mmap 分配的内存由 munmap 释放,内存释放时将立即归还操作系统。

默认情况下,大于等于128KB的内存分配会调用 mmap/mummap,小于128KB的内存请求调用 brk,但可以通过修改M_MMAP_THRESHOLD 值来调整。
另外, Glibc2.29有一个新特性: M_MMAP_THRESHOLD 可以动态调整。
M_MMAP_THRESHOLD的值在128KB到32MB(32位机)或者64MB(64位机)之间动态调整,如:当申请并释放一个大小为2MB的内存后, M_MMAP_THRESHOLD的值被调整为2M到2M + 4K之间的一个值。因此,当应用程序中申请的内存空间数量多,且先后申请的内存空间的大小变化比较大时,再申请一段大的内存后, M_MMAP_THRESHOLD的值被调大,后续的内存申请空间大小 < M_MMAP_THRESHOLD时将使用 brk 申请,而 brk 需要等到高地址内存释放以后,低地址内存才能释放。当应用程序没有释放高地址内存时,就导致大量低地址内存空间不能及时释放,从而产生“内存空洞”,导致系统内存不足。

3、解决方法

  • 进程启动时,使用 int mallopt(int param, int value) 函数显式地设置 M_MMAP_THRESHOLD 的值为128K,关闭M_MMAP_THRESHOLD动态调整特性【图1-1】
  • 优化应用程序中内存管理方式,不要频繁申请、释放内存空间,减少内存碎片。

【图1-1】
M_MMAP_THRESHOLD


  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值