c/c++中的内存精讲之内存池

一.堆分配算法

前言:

任意时刻程序发出请求,要么申请一段空间、要么释放一段已申请空间。而且申请的空间小到几个字节,大到几GB,所以堆的管理显得有些复杂。

1.malloc() 堆内存分配方法:

  1. malloc的内存管理交给系统去做:

    原因是内核就是管理者进程,可以提供个系统调用就可以让malloc使用这个系统调用去申请内存,但是系统调用的开销很大,来回切换进程,所以这么做影响程序性能。

  2. malloc向内存申请一块适当的堆空间, 自己管理这块空间:(较优做法)

2.malloc和free的分配算法:

img

程序运行期间堆内存从低地址向高地址连续分配、随着内存的释放,会出现不连续的空间空间。

当程序需要内存时,会在白色空闲区域寻找合适的空间,如果空间不够就会向操作系统申请(发生系统调用),这是为了程序内存的连续性,所以不会连接几个空闲区域。

3.内存块:

img

next:指向下一个内存块。

used:表示当前内存块是否被调用。

pre:指向上一个内存块,构成双向链表。

这是因为malloc算法会在空闲区域使用指定的空间,剩下的还是作为空闲空间,这样会有很多不连续的空闲空间,而free算法释放一段使用过的空间之后会把当前和之前空闲空间合并为一个大的空闲空间。这么看的话malloc和free就是已经申请的一段堆空间里面合并和分拆的操作,下次再使用内存时候就在当前分配好的内存中分配,不需要向系统去申请,上面也说到向系统申请内存就是系统调用,很影响程序性能。

栈内存的分配像数据结构里的栈,而堆内存的分配就像数据结构的链表。
不过这种链式分配方式也有几点问题:
  1. 很多小的空闲空间很难再被分配,所以会生成很多内存碎片。
  2. 一旦链表里的next和pre指针被破坏,整个堆就会无法工作,然后这些数据就会很容易被内存越界读取到。
  3. 经常分配和释放会导致链表过长,增加遍历时间。

4.内存池

还是上面所说到的malloc会向系统申请大小适当的内存来自己管理,这么做就是减少系统调用,这段申请的适当大小的空间就是内存池。 
内存池的算法就是管理已经申请的适当大小空间。

程序员自己分配释放内存带来了很多便利,同时也带来了很多风险,之所以之后的高级语言java、python、js等都是用虚拟机的机制管理这段内存池,回收垃圾内存。

5.池化技术

除了内存池,还有线程池、连接池、对象池、都是一样的池化技术。

拿线程池来讲主要思想:先开启一堆线程,让他们处于睡眠状态,当受到客户端的请求时唤醒某个线程处理任务,结束之后又睡眠,自己管理、以备不时之需。

posted @ 2020-03-12 21:13  hornets  阅读(466)  评论(0)    收藏  举报