目录
内存申请和释放
常见的如:库函数malloc/free、allocate/deallocate, 运算符new和delete,后面两对申请和释放内存实质也是调用了malloc/free,只是做了一些额外的处理。
malloc的分配内存有两个系统调用(不考虑共享内存),一个brk,一个mmap。一般而言,对于内存小于等于128k的调用brk,大于128k的则调用mmap。内存释放的系统调用为sbrk和unmmap.。
brk是将数据段(.data)的最高地址指针_edata往高地址推;mmap是在进程的虚拟地址空间中(堆和栈中间,称为文件映射区域的地方)找一块空闲的虚拟内存。这两种方式分配的都是虚拟内存,没有分配物理内存。在第一次访问已分配的虚拟地址空间的时候,发生缺页中断,操作系统负责分配物理内存,然后建立虚拟内存和物理内存之间的映射关系。
其他链接:
Linux系统下深究一个malloc/brk/sbrk新内存后的page fault问题
内存池
定义:是一种动态内存分配与管理技术,内存池则是在真正使用内存之前,先申请分配一大块内存(内存池)留作备用。当程序员申请内存时,从池中取出一块动态分配,当程序员释放时,将释放的内存放回到池内,再次申请,就可以从池里取出来使用,并尽量与周边的空闲内存块合并。若内存池不够时,则自动扩大内存池,从操作系统中申请更大的内存池。
作用:当用户向操作系统申请内存次数过多时,容易产生内存碎片(分为外部和内部碎片),为了减少内存碎片的产生,因此提出了内存池技术。
内存池能够减少碎片产生的原理简单如下:假设总内存为4G,如果不设置内存池,是在4G范围的长度内进行内存申请,是按照算法分布在4G内存四处。如果设置内存池(0.5G),那么只会在小范围内进行内存的申请和释放,其他3.5G不受到影响 。 有点类似于把一只拆家狗从卧室关到笼子里面,减少它破坏的范围。
参考链接:
linux内存申请释放
Glibc内存管理器首先会向内核申请一大块内存(内存池),用户调用malloc接口时,实际上是从Glibc内存管理器中获取内存,调用free释放内存时,也是将其归还给Glibc内存管理器,Glibc内存管理器充当了二道贩子的角色。
拓展链接:
内存泄漏
在程序运行过程中,用户忘记释放内存或者无法释放内存,导致申请的内存没有归还给操作系统。对于守护(常驻)进程来说,持续的内存泄漏是一场噩梦,最终会导致用户无法申请够用的内存。而对于用完即释放的进程来说,有少量的内存泄漏也不会对整体程序产生影响,因为该进程退出后将其所持有的内存资源归还给操作系统。
检测方法
解决方法
A,智能指针,采用智能指针自动帮忙销毁内存。
B,采用valgrid等工具扫码代码
B,销毁进程,对于结束任务后的进程及时销毁,避免内存泄漏。