pangudashu / php7-internal

PHP7内核剖析
3.42k stars 885 forks source link

refcount实际运行结果和文档不一致 #41

Open shengbinxu opened 3 years ago

shengbinxu commented 3 years ago

在下面这篇文章中: https://github.com/pangudashu/php7-internal/blob/master/2/zval.md 有个demo:

$a = "time:" . time();   //$a       ->  zend_string_1(refcount=1)
$b = $a;                 //$a,$b    ->  zend_string_1(refcount=2)
$c = $b;                 //$a,$b,$c ->  zend_string_1(refcount=3)

unset($b);               //$b = IS_UNDEF  $a,$c ->  zend_string_1(refcount=2)

我用php7.0实际运行的结果是:

<?php
$a = "time:" . time();   //$a       ->  zend_string_1(refcount=1)
debug_zval_dump($a);
$b = $a;                 //$a,$b    ->  zend_string_1(refcount=2)
$c = $b;                 //$a,$b,$c ->  zend_string_1(refcount=3)
debug_zval_dump($a);

unset($b);               //$b = IS_UNDEF  $a,$c ->  zend_string_1(refcount=2)

debug_zval_dump($a);

输出:

string(15) "time:1629940681" refcount(2)
string(15) "time:1629940681" refcount(4)
string(15) "time:1629940681" refcount(3)

想请教下,是什么原因导致了这种差异?

blogdaren commented 3 years ago

首先两个答案都是正确的,只是调试的上下文和视角存在差异: 原因是: 调用debug_zval_dump()时传参又发生了一次引用【opcode: ZEND_SEND_VAR】, 所以该函数执行期间引用计数是要+1的,执行完后执行栈以及参数会释放掉,引用计数又-1。 作者的例子是从纯gdb角度调试来看问题的,所以更接近我们自然的理解。

huanghantao commented 3 years ago

@shengbinxu 别用debug_zval_dump,这个函数基本不维护了,也很反人类,你可以用这个函数打印引用变量试试,理解起来更加的头疼。

安装个xdebug,然后调用xdebug_debug_zval