PHP垃圾回收机制----引用计数基础知识

<?php
// PHP垃圾回收机制案例: 参考php手册


// --------------------标量类型--------------------
// tip:每个php变量存在一个叫"zval"的变量容器中,该容器中包含变量的类型和值,"is_ref":是否是引用变量,"refcount":引用计数

// ex:生成一个新的 zval容器
$a = 'new string'; 
// ex:显示 zval容器 信息
xdebug_debug_zval('a'); // a:(refcount=1, is_ref=0),string 'new string' (length=10)

// ex:增加 zval容器的引用计数
$c = $b = $a; 
xdebug_debug_zval('a'); // a:(refcount=3, is_ref=0),string 'new string' (length=10)


xdebug_debug_zval('b'); // b:(refcount=3, is_ref=0),string 'new string' (length=10)
xdebug_debug_zval('c'); // c:(refcount=3, is_ref=0),string 'new string' (length=10)
// tip:此时只有一个容器, 因为当没必要时,php不会去复制已生成的变量容器
// 此时这个变量容器被变量 a ,变量 b和变量c关联.


unset($b); // ex:减少引用计数
xdebug_debug_zval('a'); // a:(refcount=2, is_ref=0),string 'new string' (length=10)
// tip:unset 删除变量时,refcount 变量计数减一,此时只有$a,$b 指向该变量容器


unset($a);
unset($c);
var_dump($a);
// tip:此时 recount为 0,变量被删除
// 当recount 变为 0 时,包含类型和值的这个变量容器就会从内存中删除。


// --------------------复合类型--------------
echo '--------------复合类型------------<br/>';

$a = array(
    'name' => 'junior',
    'age'  => 18
);
xdebug_debug_zval('a'); 
// a:(refcount=1, is_ref=0),
// array (size=2)
//   'name' => (refcount=1, is_ref=0),string 'junior' (length=6)
//   'age' => (refcount=1, is_ref=0),int 18


// ex:添加一个已经存在的元素到数组中
$a['love'] =  $a['name'];
xdebug_debug_zval('a'); 
// a:(refcount=1, is_ref=0),
// array (size=3)
//   'name' => (refcount=2, is_ref=0),string 'junior' (length=6)
//   'age' => (refcount=1, is_ref=0),int 18
//   'love' => (refcount=2, is_ref=0),string 'junior' (length=6)


// $a = array('one');
// xdebug_debug_zval('a'); 
// // $b = &$a;
// $c = $a;
// $b = &$c;

// xdebug_debug_zval('b'); 
// xdebug_debug_zval('c'); 
// xdebug_debug_zval('a'); 



// 清理变量容器问题
echo '------------内存泄漏问题-----------<br/>';
$a = array('one');
xdebug_debug_zval('a');
// a:(refcount=1, is_ref=0),
// array (size=1)
//   0 => (refcount=1, is_ref=0),string 'one' (length=3)

$a[] = &$a;
xdebug_debug_zval('a');
// a:(refcount=2, is_ref=1),
// array (size=2)
//   0 => (refcount=1, is_ref=0),string 'one' (length=3)
//   1 => (refcount=2, is_ref=1),
//     &array

// unset($a);
// (refcount=1, is_ref=1)=array (
//     0 => (refcount=1, is_ref=0)='one',
//     1 => (refcount=1, is_ref=1)=...
//  )

// tip: unset($a) 后引用计数减一,尽管不再有某个作用域中的任何符号指向这个结构(就是变量容器),
// 由于数组元素"1"仍然指向数组本身,所以这个容器不能被清除
// 因为没有另外的符号指向它,用户没有办法清除这个结构,结果就会导致内存泄漏
// 庆幸的是, php将在脚本执行结束时清除这个数据结构, 但是在php清除之前,将耗费不少内存.
// 同样的情况也会发生在对象上,实际上对象更有可能出现这种情况,因为对象总是隐式的被引用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值