欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

PHP GC回收機(jī)制實例詳解

 更新時間:2024年01月26日 09:06:29   作者:F12~  
GC的全稱是Garbage Collection也就是垃圾回收的意思,在PHP中,是使用引用計數(shù)和回收周期來自動管理內(nèi)存對象的,當(dāng)一個對象被設(shè)置為NULL,或者沒有任何指針指向時,他就會變成垃圾,被GC機(jī)制回收掉,這篇文章主要介紹了PHP GC回收機(jī)制詳解 ,需要的朋友可以參考下

前言

GC的全稱是Garbage Collection也就是垃圾回收的意思,在PHP中,是使用引用計數(shù)和回收周期來自動管理內(nèi)存對象的,當(dāng)一個對象被設(shè)置為NULL,或者沒有任何指針指向時,他就會變成垃圾,被GC機(jī)制回收掉。

環(huán)境配置

php.ini終配置好xdebug,xdebug_debug_zval是用來查看容器變量內(nèi)容的函數(shù)

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

在PHP GC機(jī)制中,當(dāng)程序終止時就會讓變量的refcount減1,如果refcount-1為0的話,就會銷毀回收該變量

引用計數(shù)

is_ref表示該變量是否被引用,操作系統(tǒng)學(xué)的好的同學(xué)應(yīng)該很容易理解該內(nèi)容

<?php 
  $a = "F12";
  $b = &$a;
  xdebug_debug_zval("a");
?>
# 運(yùn)行結(jié)果
a: (refcount=2, is_ref=1)='F12'

$b是$a的引用,所以is_ref=1,同時refcount也會加1,因為此時是有兩個變量的(兩變量指向同一個地址),所以銷毀時要讓refcount減2。
當(dāng)變量是array類型時,也是一樣的規(guī)則

<?php 
  $a = "F12";
  $arr = array(0=>"test", 1=>&$a);
  xdebug_debug_zval("arr");
?>
# 運(yùn)行結(jié)果
arr: (refcount=1, is_ref=0)=array (0 => (refcount=1, is_ref=0)='test', 1 => (refcount=2, is_ref=1)='F12')

如果我們在引用前將$a銷毀會發(fā)生什么?

<?php 
  $a = "F12";
  unset($a);
  $arr = array(0=>"test", 1=>&$a);
  xdebug_debug_zval("a");
  xdebug_debug_zval("arr");
?>
# 運(yùn)行結(jié)果
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");
?>
# 運(yùn)行結(jié)果
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);
# 運(yùn)行結(jié)果
construct(1)
construct(2)
construct(3)
destruct(3)
destruct(2)
destruct(1)

先創(chuàng)建的對象最后銷毀,看看變量的內(nèi)容情況:

可以看到refcount為1,所以當(dāng)程序結(jié)束時,減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);
# 運(yùn)行結(jié)果
construct(1)
destruct(1)
construct(2)
construct(3)
destruct(3)
destruct(2)

可以看到第一個gc對象,創(chuàng)建完就被回收了,因為沒被其它變量引用,它的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!,但是因為觸發(fā)了異常,所以對象并沒有被回收

我們修改一下代碼:

<?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");

這里我們我們修改序列化的內(nèi)容,將$a[0]隨便指向誰,從而使new的gc對象沒有引用的變量,所以觸發(fā)提前回收,跟上面舉的直接new gc,并不賦值是一個道理

思路二

這種方法更加簡單粗暴,我們只需要讓序列化的數(shù)據(jù)出錯,那么當(dāng)反序列化時出錯時,也會讓該對象提前回收

<?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!

到此這篇關(guān)于PHP GC回收機(jī)制詳解 的文章就介紹到這了,更多相關(guān)PHP GC回收機(jī)制內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 變量在 PHP7 內(nèi)部的實現(xiàn)(二)

    變量在 PHP7 內(nèi)部的實現(xiàn)(二)

    在上篇文章給大家介紹了變量在 PHP7 內(nèi)部的實現(xiàn)(一),本篇繼續(xù)給大家介紹php7內(nèi)部實現(xiàn)相關(guān)知識,感興趣的朋友通過本篇文章一起學(xué)習(xí)吧
    2015-12-12
  • PHP處理會話函數(shù)大總結(jié)

    PHP處理會話函數(shù)大總結(jié)

    在PHP開發(fā)中,比起Cookie,Session 是存儲在服務(wù)器端的會話,相對安全,并且不像 Cookie 那樣有存儲長度限制,PHP處理會話函數(shù)包括:session_start、session_register、session_is_registered、session_unregister、Session_destroy等等,這里詳細(xì)介紹下php處理會話函數(shù)
    2015-08-08
  • Laravel日志用法詳解

    Laravel日志用法詳解

    這篇文章主要介紹了Laravel日志用法,結(jié)合實例形式較為詳細(xì)的分析了Laravel日志的功能、定義、使用方法與相關(guān)注意事項,需要的朋友可以參考下
    2016-10-10
  • php注冊和登錄界面的實現(xiàn)案例(推薦)

    php注冊和登錄界面的實現(xiàn)案例(推薦)

    下面小編就為大家?guī)硪黄猵hp注冊和登錄界面的實現(xiàn)案例(推薦)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-10-10
  • THinkPHP獲取客戶端IP與IP地址查詢的方法

    THinkPHP獲取客戶端IP與IP地址查詢的方法

    這篇文章主要介紹了THinkPHP獲取客戶端IP與IP地址查詢的方法,結(jié)合實例形式分析了thinkPHP針對客戶端IP地址操作的相關(guān)函數(shù)與使用技巧,需要的朋友可以參考下
    2016-11-11
  • php使用FFmpeg接口獲取視頻的播放時長、碼率、縮略圖以及創(chuàng)建時間

    php使用FFmpeg接口獲取視頻的播放時長、碼率、縮略圖以及創(chuàng)建時間

    本篇文章主要介紹了php使用FFmpeg接口獲取視頻的播放時長、碼率、縮略圖以及創(chuàng)建時間,具有一定的參考價值,有需要的可以了解一下。
    2016-11-11
  • Thinkphp中volist標(biāo)簽mod控制一定記錄的換行BUG解決方法

    Thinkphp中volist標(biāo)簽mod控制一定記錄的換行BUG解決方法

    這篇文章主要介紹了Thinkphp中volist標(biāo)簽mod控制一定記錄的換行BUG解決方法,涉及針對標(biāo)簽執(zhí)行語句順序的修改,非常具有實用價值,需要的朋友可以參考下
    2014-11-11
  • laravel 判斷查詢數(shù)據(jù)庫返回值的例子

    laravel 判斷查詢數(shù)據(jù)庫返回值的例子

    今天小編就為大家分享一篇laravel 判斷查詢數(shù)據(jù)庫返回值的例子,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-10-10
  • PHPThumb圖片處理實例

    PHPThumb圖片處理實例

    這篇文章主要介紹了PHPThumb圖片處理實例,例如生成縮略圖、圖片尺寸調(diào)整、圖片截取、圖片加水印、圖片旋轉(zhuǎn)等,需要的朋友可以參考下
    2014-05-05
  • 微信公眾號開發(fā)之文本消息自動回復(fù)php代碼

    微信公眾號開發(fā)之文本消息自動回復(fù)php代碼

    這篇文章主要為大家詳細(xì)介紹了微信公眾號開發(fā)之文本消息自動回復(fù)php代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-08-08

最新評論