PHP GC回收机制详解

2024-03-08 0 2,477

猪小侠源码,https://www.20zxx.cn/

前言

GC的全称是Garbage Collection也就是垃圾回收的意思,在PHP中,是使用引用计数和回收周期来自动管理内存对象的,当一个对象被设置为NULL,或者没有任何指针指向时,他就会变成垃圾,被GC机制回收掉。

环境配置

php.ini终配置好xdebug,xdebug_debug_zval是用来查看容器变量内容的函数

<?php
$a = "F12";
xdebug_debug_zval("a");
?>

PHP GC回收机制详解
在PHP GC机制中,当程序终止时就会让变量的refcount减1,如果refcount-1为0的话,就会销毁回收该变量

引用计数

is_ref表示该变量是否被引用,操作系统学的好的同学应该很容易理解该内容

<?php
$a = "F12";
$b = &$a;
xdebug_debug_zval("a");
?>

# 运行结果
a: (refcount=2, is_ref=1)='F12'

$b是$a的引用,所以is_ref=1,同时refcount也会加1,因为此时是有两个变量的(两变量指向同一个地址),所以销毁时要让refcount减2。
当变量是array类型时,也是一样的规则

<?php
$a = "F12";
$arr = array(0=>"test", 1=>&$a);
xdebug_debug_zval("arr");
?>
# 运行结果
arr: (refcount=1, is_ref=0)=array (0 => (refcount=1, is_ref=0)='test', 1 => (refcount=2, is_ref=1)='F12')

如果我们在引用前将$a销毁会发生什么?

<?php
$a = "F12";
unset($a);
$arr = array(0=>"test", 1=>&$a);
xdebug_debug_zval("a");
xdebug_debug_zval("arr");
?>
# 运行结果
a: (refcount=2, is_ref=1)=NULL
arr: (refcount=1, is_ref=0)=array (0 => (refcount=1, is_ref=0)='test', 1 => (refcount=2, is_ref=1)=NULL)

<?php
$a = "F12";
$arr = array(0=>"test", 1=>&$a);
unset($a);
xdebug_debug_zval("a");
xdebug_debug_zval("arr");
?>
# 运行结果
a: no such symbol
arr: (refcount=1, is_ref=0)=array (0 => (refcount=1, is_ref=0)='test', 1 => (refcount=1, is_ref=1)='F12')

第一种情况,$a没有被销毁,因为在之后又引用了$a,所以$a只是指向了一个NULL,第二种情况就把$a销毁了

PHP GC在反序列化中的使用

一个简单的demo

<?php
class gc{
public $num;
public function __construct($num)
{
$this->num=$num;
echo "construct(".$num.")"."\\n";
}
public function __destruct()
{
echo "destruct(".$this->num.")"."\\n";
}
}
$a=new gc(1);
$b=new gc(2);
$c=new gc(3);

# 运行结果
construct(1)
construct(2)
construct(3)
destruct(3)
destruct(2)
destruct(1)

先创建的对象最后销毁,看看变量的内容情况:
PHP GC回收机制详解
可以看到refcount为1,所以当程序结束时,减1就会被回收
如果我们不把new的gc对象赋值给$a会怎样?

<?php
class gc{
public $num;
public function __construct($num)
{
$this->num=$num;
echo "construct(".$num.")"."\\n";
}
public function __destruct()
{
echo "destruct(".$this->num.")"."\\n";
}
}
new gc(1);
$b=new gc(2);
$c=new gc(3);

# 运行结果
construct(1)
destruct(1)
construct(2)
construct(3)
destruct(3)
destruct(2)

可以看到第一个gc对象,创建完就被回收了,因为没被其它变量引用,它的refcount一开始就是0,所以直接被回收

绕过Exception异常

思路一

一个简单的demo:

<?php
class gc{
public $num;
public function __construct($num)
{
$this->num=$num;
}
public function __destruct()
{
echo "Hello World!";
}
}
$a = new gc(1);
$ser = serialize($a);
$b = unserialize($ser);
throw new Exception("F12 is bad");

正常来说会输出一个Hello World!,但是因为触发了异常,所以对象并没有被回收
PHP GC回收机制详解
我们修改一下代码:

<?php
class gc{
public $num;
public function __construct($num)
{
$this->num=$num;
}
public function __destruct()
{
echo "Hello World!";
}
}
$a = array(0=>new gc(1),1=>1);
$ser = serialize($a);
echo $ser;
$ser = 'a:2:{i:0;O:2:"gc":1:{s:3:"num";i:1;}i:0;i:1;}';
$b = unserialize($ser);
throw new Exception("F12 is bad");

这里我们我们修改序列化的内容,将$a[0]随便指向谁,从而使new的gc对象没有引用的变量,所以触发提前回收,跟上面举的直接new gc,并不赋值是一个道理
PHP GC回收机制详解

思路二

这种方法更加简单粗暴,我们只需要让序列化的数据出错,那么当反序列化时出错时,也会让该对象提前回收

<?php
class gc{
public $num;
public function __construct($num)
{
$this->num=$num;
}
public function __destruct()
{
echo "Hello World!";
}
}
$a = new gc(1);
$ser = serialize($a);
echo $ser;
$ser = 'O:2:"gc":1:{s:3:"num";i:1;';
$b = unserialize($ser);
throw new Exception("F12 is bad");

这里我们删去一个},依然输出了Hello World!
PHP GC回收机制详解

猪小侠源码,https://www.20zxx.cn/
资源下载此资源下载价格为1小猪币,终身VIP免费,请先
由于本站资源来源于互联网,以研究交流为目的,所有仅供大家参考、学习,不存在任何商业目的与商业用途,如资源存在BUG以及其他任何问题,请自行解决,本站不提供技术服务! 由于资源为虚拟可复制性,下载后不予退积分和退款,谢谢您的支持!如遇到失效或错误的下载链接请联系客服QQ:442469558

:本文采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可, 转载请附上原文出处链接。
1、本站提供的源码不保证资源的完整性以及安全性,不附带任何技术服务!
2、本站提供的模板、软件工具等其他资源,均不包含技术服务,请大家谅解!
3、本站提供的资源仅供下载者参考学习,请勿用于任何商业用途,请24小时内删除!
4、如需商用,请购买正版,由于未及时购买正版发生的侵权行为,与本站无关。
5、本站部分资源存放于百度网盘或其他网盘中,请提前注册好百度网盘账号,下载安装百度网盘客户端或其他网盘客户端进行下载;
6、本站部分资源文件是经压缩后的,请下载后安装解压软件,推荐使用WinRAR和7-Zip解压软件。
7、如果本站提供的资源侵犯到了您的权益,请邮件联系: 442469558@qq.com 进行处理!

猪小侠源码-最新源码下载平台 PHP教程 PHP GC回收机制详解 http://www.20zxx.cn/813748/xuexijiaocheng/qes.html

猪小侠源码,优质资源分享网

常见问题
  • 本站所有资源版权均属于原作者所有,均只能用于参考学习,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担
查看详情
  • 最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,建议提前注册好百度网盘账号,使用百度网盘客户端下载
查看详情

相关文章

官方客服团队

为您解决烦忧 - 24小时在线 专业服务