游戏内存中会出现的问题
内存泄露
忘记回收内存,函数退栈导致丢失了指针,就再也找回不了new的内存地址,这时内存一直就会被占用着。
内存碎片
由于对堆内存的分配/释放的顺序是随机的,导致申请的内存块随机分布于原始内存,倘若分布不是连续的(随机顺序往往导致多个内存块都是相隔开的),那么便会产生“洞”。
随着时间推移,堆内存越来越多出现这些“洞”,导致可用的自由内存块被拆分成多个小内存块。
这就导致即使有足够的自由内存,分配请求仍然可能会失败。
内存页切换问题
虚拟内存系统把不连续的物理内存块(即内存页)映射至虚拟地址空间,使内存页对于应用程序来说看上去是连续的。
在支持虚拟内存的操作系统上,多次使用原生C/C++内存分配,有可能其中几次是一个内存页,几次是第二个内存页,又有几次是第三个内存页的内容....在重复共同使用这些内存的时候有可能导致昂贵的切换内存页开销。
内存池
对C++内存分配进行适合当前程序的封装就显得尤为重要,这样C++程序员就能在封装完内存机制后减少大量心思警惕内存问题。
而如何封装还能高效的使用内存,就成了一门学问——内存池管理。
预先通过new或者malloc(原生的内存分配函数)分配好一个大块内存(挖好池子),然后提供这块内存池的再分配函数。
当程序员需要分配小块堆内存时,可以向这个内存池请求分配小内存。
- 由于内存池本身往往内存比较大,所以内存池本身的分配释放不易产生内存碎片。
- 即使程序员由于操作失误导致内存池内部出现内存碎片或者内存泄漏问题,但是整个内存池本身只要正确释放,内存问题就不会向外扩张。
- 一次性分配好大内存,尽可能减少了多次使用原生C/C++复杂的内存分配操作开销(因为相对来说自定义的再分配操作往往开销很小)。