php - 垃圾回收机制GC

引言

从事php开发也有两年了,一次融360的面试现场,有被问到php的垃圾回收机制,有点木哈。因为做了php很久,这是一个不太会过多关注的一个点,gc更多的是停留在上学时候c++的时代,废话有点多,别的文章的分析也比较全,我简单说说我的理解吧!let‘s go!

初探unset 和 null

在php的使用中,对于变量的严谨化操作,可能就是这两个方式了。但是,你知道它俩的区别吗?对一个变量unset之后,是否就等于已经内存回收了呢?继续听课。

zval

php中的一个概念zval,你是否听说过,你可以nginx中配置xdebug,从而使用

xdebug_debug_zval($a) 查看变量的当前使用状态

该函数有两个返回的值:refcount和is_ref, 分别表示:

refcount 表示该变量及其赋值的变量的使用次数。
is_ref表示以地址引用的方式赋值的状态。

其中,refcount是特别重要的一个概念。

核心的一句话

再谈unset和null

  1. unset是断开变量与内存块联系,并且把zval的refcount-1.但是内容是否会回收,要看recount是否变为0。
    比如:
$a = "new string";
$b = $a;
xdebug_debug_zval( 'a' );

其返回的是
a: (refcount=2, is_ref=0)='new string'
即使unset($a),而以上的refcount=1,表示还有变量再使用,内存不会回收。
2. ¥a=null是断开链接,并且将recount变为0.从而垃圾回收。

所以现在懂了?

内存溢出

看下面的代码:

$a = array( 'one' );
$a[] =& $a;
xdebug_debug_zval( 'a' );

¥a的数组,导致了¥a的内存使用情况refcount变为了2,当unset($a)时,只减了1,refcount变为了1,仍然不能回收,这样就导致了内存泄露。
这也是php5.3以前会有的情况。

防止php内存泄露

php5.3及其以上版本,针对内存溢出,升级了gc算法,加入了缓存区,每个变量都只出现一次,当有自身引用的变量,不加1。则不会内存溢出。

10-03 13:58