使用的是 "引用计数" 方式进行回收. 简单地理解的话, 就是每个分配的内存区域都有一个计数器, 记录有多少个变量指针指向这片内存. 当指向该片内存的指针数量为 0, 那么该片内存区域就可以被回收.
引用计数计数简单, 强大, 但是有一个致命的缺陷, 就是环状引用. 考虑以下的代码:
Php 代码
- $a = array();
- $a[] = &$a;
- unset($a);
变量 $a 引用了自己, 形成了一个环.$a 被 unset 了, 可是由于存在环状引用, 因此 $a 之前指向的内存的引用计数为 1, 因此该内存区域不会被垃圾回收机制回收.
PHP5.3 针对这个重大的缺陷做了优化. 虽然其基础仍然是引用计数, 但是在做了一些改良, 能够将环状引用导致的内存泄露控制在一定的规模以内. 当然, 这并不是说你可以随便滥用内存, 编写代码时仍然要小心为上!
其他要点:
1.PHP 脚本运行完毕, 该脚本申请的所有内存空间都会释放, 不管是否存在环状引用. 因此环状引用内存泄露的问题一般只影响长时间运行的程序脚本.
2. 垃圾回收机制需要满足一定的条件才会执行. 因此 unset 后, 系统并不一定会立即回收垃圾.
3.unset 的作用.
"unset 只是断开一个变量到一块内存区域的连接, 同时将该内存区域的引用计数 - 1". 也就是说, 如果有一个以上的变量指向同一个内存区域, 或者存在环状引用, 那么 unset 不会使内存区域释放. 断开也说明 unset 并不会直接删除内存区域, 而只是改变其引用计数而已.
4.$xx=null 的作用.
"$a = null 是直接将 $a 指向的数据结构置空, 同时将其引用计数归 0". 根据我对这个定义的理解,=null 操作可以立即释放掉内存空间! 因此很多 PHP 技巧中不厌其烦地对我们说, 先将变量设为 null, 再 unset. 理解其深层原理后, 我才彻底理解了这样做的原因!=null 才是王道!
来源: http://www.bubuko.com/infodetail-2713962.html