如果您发现 refcount 的解释令人困惑,Xdebug 扩展提供了一个类似于此函数的功能,但由于变量名作为字符串传递,因此 xdebug_debug_zval() 不会用它自己对 zval 的引用来在 refcount 上乱写。
(PHP 4 >= 4.2.0, PHP 5, PHP 7, PHP 8)
debug_zval_dump — 将内部 zval 结构的字符串表示形式转储到输出
将内部 zval(Zend 值)结构的字符串表示形式转储到输出。这主要用于理解或调试 Zend 引擎或 PHP 扩展的实现细节。
value
要转储的变量或值。
values
要转储的更多变量或值。
不返回值。
示例 #1 debug_zval_dump() 示例
<?php
$var1 = 'Hello';
$var1 .= ' World';
$var2 = $var1;
debug_zval_dump($var1);
?>
以上示例将输出
string(11) "Hello World" refcount(3)
注意: 理解
refcount
如果不详细了解引擎的实现,此函数显示的
refcount
值可能会让人感到困惑。Zend 引擎使用引用计数来实现两个不同的目的
- 使用称为“写时复制”的技术优化内存使用,其中多个持有相同值的变量指向内存中的同一副本。当任何一个变量被修改时,它将指向内存中的一个新副本,而原始副本的引用计数将减少 1。
- 跟踪已通过引用分配或传递的变量(参见 引用详解)。此引用计数存储在指向当前值的 zval 的一个单独的引用 zval 上。此附加 zval 当前不会被 debug_zval_dump() 显示。
因为 debug_zval_dump() 以按值传递的正常参数的形式接收其输入,所以将使用写时复制技术来传递它们:而不是复制数据,refcount 将在函数调用期间增加一个。如果函数在接收参数后修改了参数,那么将创建一个副本;由于它没有这样做,因此它将显示比调用范围中更高的 refcount。
参数传递还阻止 debug_zval_dump() 显示已通过引用分配的变量。为了说明,考虑上述示例的略微修改版本
<?php
$var1 = 'Hello';
$var1 .= ' World';
// 将三个变量作为引用指向同一个值
$var2 =& $var1;
$var3 =& $var1;
debug_zval_dump($var1);
?>以上示例将输出
string(11) "Hello World" refcount(2)虽然 $var1、$var2 和 $var3 作为引用链接在一起,但只有值传递给 debug_zval_dump()。该值被引用集使用一次,并在 debug_zval_dump() 内部使用一次,因此显示 refcount 为 2。
由于引擎针对不同数据类型进行了优化,因此出现了进一步的复杂性。某些类型(如整数)不使用“写时复制”,因此根本不显示 refcount。在其他情况下,refcount 显示内部使用的额外副本,例如当文字字符串或数组存储为代码指令的一部分时。
如果您发现 refcount 的解释令人困惑,Xdebug 扩展提供了一个类似于此函数的功能,但由于变量名作为字符串传递,因此 xdebug_debug_zval() 不会用它自己对 zval 的引用来在 refcount 上乱写。