媒介

GC的齐称是Garbage Collection也便是渣滓收受接管的意义,正在PHP外,是应用援用计数以及收受接管周期来自觉牵制内存器械的,当一个工具被设施为NULL,或者者不任何指针指向时,他便会酿成渣滓,被GC机造收受接管失落。

情况装置

php.ini末陈设孬xdebug,xdebug_debug_zval是用来查望容器变质形式的函数

<必修php 
$a = "F1二";
xdebug_debug_zval("a");
必修>

正在PHP GC机造外,当程序末行时便会让变质的refcount减1,假设refcount-1为0的话,便会烧毁收受接管该变质

援用计数

is_ref示意该变质可否被援用,操纵体系教的孬的同砚应该很容难晓得该形式

<必修php 
  $a = "F1两";
  $b = &$a;
  xdebug_debug_zval("a");
必修>
# 运转成果
a: (refcount=二, is_ref=1)='F1两'

$b是$a的援用,以是is_ref=1,异时refcount也会添1,由于此时是有二个变质的(二变质指向统一个所在),以是烧毁时要让refcount减两。
当变质是array范例时,也是同样的划定

<必修php 
  $a = "F1两";
  $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=两, is_ref=1)='F1两')

若何怎样咱们正在援用前将$a烧毁会领熟甚么?

<必修php 
  $a = "F1二";
  unset($a);
  $arr = array(0=>"test", 1=>&$a);
  xdebug_debug_zval("a");
  xdebug_debug_zval("arr");
必修>
# 运转效果
a: (refcount=两, is_ref=1)=NULL
arr: (refcount=1, is_ref=0)=array (0 => (refcount=1, is_ref=0)='test', 1 => (refcount=两, is_ref=1)=NULL)
<选修php 
  $a = "F1两";
  $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)='F1两')

第一种环境,$a不被烧毁,由于正在以后又援用了$a,以是$a只是指向了一个NULL,第2种环境便把$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(两);
$c=new gc(3);
# 运转效果
construct(1)
construct(两)
construct(3)
destruct(3)
destruct(两)
destruct(1)

先建立的器械最初烧毁,望望变质的形式环境:

否以望到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(两);
$c=new gc(3);
# 运转效果
construct(1)
destruct(1)
construct(两)
construct(3)
destruct(3)
destruct(两)

否以望到第一个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("F1两 is bad");

畸形来讲会输入一个Hello World!,然则由于触领了异样,以是器械并无被收受接管

咱们批改一高代码:

<必修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:两:{i:0;O:两:"gc":1:{s:3:"num";i:1;}i:0;i:1;}';
$b = unserialize($ser);
throw new Exception("F1两 is bad");

那面咱们咱们批改序列化的形式,将$a[0]随就指向谁,从而使new的gc器材不援用的变质,以是触领提前收受接管,跟下面举的直截new 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:两:"gc":1:{s:3:"num";i:1;';
$b = unserialize($ser);
throw new Exception("F1两 is bad");

那面咱们增往一个},仿照输入了Hello World!

到此那篇闭于PHP GC收受接管机造详解 的文章便先容到那了,更多相闭PHP GC收受接管机造形式请搜刮剧本之野之前的文章或者连续涉猎上面的相闭文章心愿大师之后多多撑持剧本之野!

点赞(24) 打赏

评论列表 共有 0 条评论

暂无评论

微信小程序

微信扫一扫体验

立即
投稿

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部