前面一章介绍了寄存器申请。
这一章节介绍内存的管理。
c++ 在 c11 之后引入动态指针后,稍微有些改善,但是相对而言,c/c++ 可以通过各种指针来绕过包括类型检查等各种限制,灵活底层的同时也确实一不注意就泄漏了。
从历史可以看到,到上世纪 90 年代,java 开始真正广泛使用,内存自动管理回收的技术才成为主流。
创建对象的回收理念:
创建后不使用的对象可以释放:
reachable 和 garbage 的定义:
这里举例说明了 reachable 和 unused 的区别。
如这里到 GC 的 B 点,是 reachable 的也是 unused 的,这里不会被回收。
回顾一下函数调用的堆栈和 AR(activation record) 结构:
在内存回收的过程中会使用到 AR 的结构
例子:
内存回收的步骤:
实现方法:
make phase 伪代码实现:
sweep phase 实现:
sweep phase 伪代码:
操作例子:
实现中需要注意的点:
还是那句话,所有的工程到了系统这层,都是各种 tricky。
具体怎么操作就不说了。
这里的指针反转是用来标记 object 的 remarkable,当深度优先遍历结束之后,需要把反转指针擦除。
这也就是为什么 c/c++ 需要 memset 初始化的原因了。
预先分配一段空间,用于资源的 copy。
具体实现步骤:
伪代码:
由于资源 copy 的速度相对较快,所以这是最快速的方法。
c/c++ 由于有指针的操作,无法判断什么存储空间中哪些是指针哪些是数据,所以无法直接 copy.
c/c++ 有保守 copy 的方法
但是还是无法避免部分内容不能 copy 的问题。
实现方案:
优缺点:
缺点 1,是如果有环路,会一直递归。
缺点 2,如果是简单操作,那么 count 计数的指令也会占用较大的资源。
但是这个方法还是很好的,很多语言都是用了引用计数来回收,如 java.
ps:在实时系统和并行系统中还会有其他的算法来对应的支撑系统特性。