php的垃圾回收机制——引用计数

  • 时间:
  • 浏览:1
  • 来源:大发5分快乐8APP下载_大发5分快乐8APP官网

   'number' => (refcount=1, is_ref=0)=42,

从以上的xdebug输出信息,让他们都看完原有的数组元素和新加进的数组元素关联到同有一四个 "refcount"2的zval变量容器. 尽管 Xdebug的输再次出现示有一四个 值为'life'的 zval 变量容器,我我觉得是同有一四个 。 函数xdebug_debug_zval()不显示有有一种信息,但有了你能通过显示内存指针信息来看完。

   'number' => (refcount=1, is_ref=0)=42

a: (refcount=1, is_ref=0)=array (

<?php
$a = array( 'meaning' => 'life', 'number' => 42 );
$a['life'] = $a['meaning'];
unset( $a['meaning'], $a['number'] );
xdebug_debug_zval( 'a' );
?>

自引用(curcular reference,被委托人是被委托人的有一四个 元素)的数组的zval

(refcount=1, is_ref=1)=array (

)

<?php
$a = "new string";
?>

以上例程会输出:

删除数组中的有一四个 元素,统统 相似于从作用域中删除有一四个 变量. 删除后,数组中的有有一种元素所在的容器的“refcount”值减少,同样,当“refcount”为0时,有有一种变量容器就从内存中被删除,下面又有一四个 例子都可以都可以 说明:

<?php
$a = array( 'meaning' => 'life', 'number' => 42 );
$a['life'] = $a['meaning'];
xdebug_debug_zval( 'a' );
?>

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

   'meaning' => (refcount=2, is_ref=0)='life',

以上例程的输出相似于:

<?php
$a = array( 'one' );
$a[] =& $a;
xdebug_debug_zval( 'a' );
?>

例5 Creating a array zval



)

当有一四个 变量被赋常量值时,就会生成有一四个 zval变量容器,如下例从前:

以上例程会输出:

   0 => (refcount=1, is_ref=0)='one',

现在,当让他们都加进有一四个 数组有有一种作为有有一种数组的元素时,事情就变得有趣,下个例子将说明有有一种。例中让他们都加入了引用操作符,怎么让php将生成有一四个 基因重组。

这时,引用次数是2,因为着同有一四个 变量容器被变量 a 和变量 b关联.当没必要时,php不必去基因重组已生成的变量容器。变量容器在”refcount“变成0时就被销毁. 当任何关联到某个变量容器的变量遗弃它的作用域(比如:函数执行过后过后开始 ),因为着对变量调用了函数 unset()时,”refcount“就会减1,下面的例子就能说明:

a: (refcount=1, is_ref=0)=array (

包含引用的简单数组的zval

图示:

例3 增加有一四个 zval的引用计数

例4 减少引用计数

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

以上例程会输出:

因为着让他们都现在执行 unset($a);,包含类型和值的有有一种变量容器就会从内存中删除。

a: (refcount=1, is_ref=0)='new string'

   'meaning' => (refcount=1, is_ref=0)='life',

例1 生成有一四个 新的zval容器

   0 => (refcount=1, is_ref=0)='one',

a: (refcount=2, is_ref=1)=array (

以上例程的输出相似于:

   1 => (refcount=1, is_ref=1)=...

例2 显示zval信息

<?php
$a = array( 'meaning' => 'life', 'number' => 42 );
xdebug_debug_zval( 'a' );
?>

当考虑像 array和object从前的复合类型时,事情就稍微有点错综复杂. 与 标量(scalar)类型的值不同,array和 object类型的变量把它们的成员或属性地处被委托人的符号表中。这因为着下面的例子将生成有一四个 zval变量容器。

例8 把数组作为有一四个 元素加进到被委托人

<?php
xdebug_debug_zval('a');
?>

   'life' => (refcount=1, is_ref=0)='life'



因为着里边的请况地处仅仅一两次倒没哪此,怎么让因为着再次出现几千次,甚至几十万次的内存泄漏,这显然是个大哪此的大问题。从前的哪此的大问题往往地处在长时间运行的脚本中,比如请求基本上不必过后过后开始 的守护应用程序(deamons)因为着单元测试中的大的套件(sets)中。后者的例子:在给巨大的eZ(有一四个 知名的PHP Library) 组件库的模板组件做单元测试时,就因为着会再次出现哪此的大问题。有时测试因为着需要耗用2GB的内存,而测试服务器很因为着都可以都可以 都可以都可以 大的内存。



a: (refcount=3, is_ref=0)='new string'

复合类型(Compound Types)

清理变量容器的哪此的大问题(Cleanup Problems)

   'life' => (refcount=2, is_ref=0)='life'

例6 加进有一四个 因为着地处的元素到数组中

跟前一天一样,对有一四个 变量调用unset,将删除有有一种符号,且它指向的变量容器中的引用次数也减1。统统有,因为着让他们都在执行完里边的代码后,对变量$a调用unset, 都可以都可以 变量 $a 和数组元素 "1" 所指向的变量容器的引用次数减1, 从"2"变成"1". 下例都可以都可以 说明:

例9 Unsetting $a

图示:

图示:

在上例中,新的变量a,是在当前作用域中生成的。怎么让生成了类型为 string 和值为new string的变量容器。在额外的有一四个 字节信息中,"is_ref"被默认设置为 FALSE,因为着都可以都可以 任何自定义的引用生成。"refcount" 被设定为 1,因为着这都可以否都可以 有一四个 变量使用有有一种变量容器. 注意到当"refcount"的值是1时,"is_ref"的值突然FALSE. 因为着你因为着安装了» Xdebug,你能通过调用函数 xdebug_debug_zval()显示"refcount"和"is_ref"的值。

图示:

)

以上例程的输出相似于:

例7 从数组中删除有一四个 元素

a: (refcount=1, is_ref=0)=array (

)

a: (refcount=2, is_ref=0)='new string'

尽管不再有某个作用域中的任何符号指向有有一种形态学 (统统 变量容器),因为着数组元素“1”仍然指向数组有有一种,统统有有有一种容器都可以 被清除 。因为着都可以都可以 另外的符号指向它,用户都可以都可以 办法清除有有一种形态学 ,结果就会因为着内存泄漏。庆幸的是,php将在脚本执行过后过后开始 时清除有有一种数据形态学 ,怎么让在php清除前一天,将耗费不少内存。因为着帮我实现分析算法,因为着要做有些像有一四个 子元素指向它的父元素从前的事情,有有一种请况就会突然地处。当然,同样的请况也会地处在对象上,实际上对象更有因为着再次出现有有一种请况,因为着对象突然隐式的被引用。

有一四个 简单数组的zval

Zvals after removal of array with a circular reference demonstrating the memory leak

以上例程的输出相似于:

把有一四个 变量赋值给另一变量将增加引用次数(refcount).

   1 => (refcount=2, is_ref=1)=...

这有一四个 zval变量容器是: a,meaning和 number。增加和减少”refcount”的规则和里边提到的一样. 下面, 让他们都在数组中再加进有一四个 元素,怎么让把它的值设为数组中已地处元素的值:

能看完数组变量 (a) 并肩也是有有一种数组的第四个元素(1) 指向的变量容器中“refcount”为 2。里边的输出结果中的"..."说明地处了递归操作, 显然在有有一种请况下因为着"..."指向原始数组。

a: (refcount=1, is_ref=0)='new string'

)