行业资讯

首页/安信10平台-安信10娱乐-工会鹊桥网【安信10注册】

2022-11-16 10:28:46 yqs888 0

首页/安信10平台-安信10娱乐-工会鹊桥网【安信10注册】报道,上周战队知识分享时,H3018大师傅讲了PHP GC回收机制的利用,学会了如何去绕过抛出异常。H3018大师傅讲述的很清楚,大家有兴趣的可以去看一下哇,链接如下
https://www.bilibili.com/video/BV16g411s7CH/这里没有怎么涉及底层原理,只是将我自己的见解简述一下,希望能对正在学习PHP反序列化的师傅有所帮助。

GC

什么是GC

Gc,全称Garbage collection,即垃圾回收机制。在PHP中有这个GC机制

PHP中的GC

在PHP中,使用引用计数回收周期来自动管理内存对象的,当一个变量被设置为NULL,或者没有任何指针指向时,它就会被变成垃圾,被GC机制自动回收掉那么这里的话我们就可以理解为,当一个对象没有被引用时,就会被GC机制回收,在回收的过程中,它会自动触发_destruct方法,而这也就是我们绕过抛出异常的关键点。

上文说到PHP是使用引用计数来进行管理的,接下来简单说一下。

引用计数

当我们PHP创建一个变量时,这个变量会被存储在一个名为zval的变量容器中。在这个zval变量容器中,不仅包含变量的类型和值,还包含两个字节的额外信息。

第一个字节名为is_ref,是bool值,它用来标识这个变量是否是属于引用集合。PHP引擎通过这个字节来区分普通变量和引用变量,由于PHP允许用户使用&来使用自定义引用,zval变量容器中还有一个内部引用计数机制,来优化内存使用。

第二个字节是refcount,它用来表示指向zval变量容器的变量个数。所有的符号存储在一个符号表中,其中每个符号都有作用域。

看接下来的这个例子

<?php$a = "new string";
xdebug_debug_zval('a'); //用于查看变量a的zval变量容器的内容?>

我们可以看到这里定义了一个变量$a,生成了类型为String和值为new string的变量容器,而对于两个额外的字节,is_refrefcount,我们这里可以看到是不存在引用的,所以is_ref的值应该是false,而refcount是表示变量个数的,那么这里就应该是1,接下来我们验证一下

安信10娱乐


接下来我们添加一个引用

<?php<?php$a="new string";
$b =&$a;
xdebug_debug_zval('a');?>

按照之前的思路,每生成一个变量就有一个zval记录其类型和值以及两个额外字节,那我们这里的话a的refcount应该是1,is_ref应该是true,接下来我们验证一下

安信10娱乐


哎,结果不同于我们所想的,这是为什么呢?因为同一变量容器被变量a和变量b关联,当没必要时,php不会去复制已生成的变量容器。所以这一个zval容器存储了ab两个变量,就使得refcount的值为2.

接下来说一下容器的销毁这个事。变量容器在refcount变成0时就被销毁。它这个值是如何减少的呢,当函数执行结束或者对变量调用了unset()函数,refcount就会减1。看个例子