查看变量引用计数及是否引用的方法

对于PHP源码阅读过程中,变量是一个非常重要的概念,更重要的是对变量的容器ZVAL理解, 如果在无法使用*nix环境进行debug,或者不想在windows环境下折腾开发环境,你可以考虑使用下面的两个方法简单的查看变量关于引用计数及是否引用的信息

debug_zval_dump函数

debug_zval_dump函数是PHP自带的标准函数。它的作用是查看一个变量在zend引擎中的引用计数、类型信息。看一个例子:

$a = 'phppan';
debug_zval_dump($a);

输出:

string(6) "phppan" refcount(2)

显示的结果与我们预期的refcount = 1不同,为什么呢?在函数参数传递时有引用计数增加操作,所以输出变量的refcount=2,因此我们在使用此函数时需要将refcount的值减去一作为真实值。

另外,debug_zval_dump支持多参数,如下代码:

$a = 'phppan';
$b = 'martin';
debug_zval_dump($a, $b);

输出:

string(6) "phppan" refcount(2) string(6) "martin" refcount(2)

由于debug_aval_dump为PHP的标准函数,则我们可以在/ext/standard/var.c中找到其定义:

PHP_FUNCTION(debug_zval_dump)

函数在实现时遍历所有传递进来的参数,调用php_debug_zval_dump函数,显示变量的引用计数和变量类型。 而在php_debug_zval_dump函数中将以变量的类型区分变量,输出相应的字符串。以 IS_LONG 为例:

php_printf("%slong(%ld) refcount(%u)\n", COMMON, Z_LVAL_PP(struc), Z_REFCOUNT_PP(struc));
#define Z_REFCOUNT_PP(ppz) Z_REFCOUNT_P(*(ppz))
#define Z_REFCOUNT_P(pz) ((pz)->refcount)

程序最终输出的refoucnt是返回的ZVAL结果中的refcount的值。

xdebug_debug_zval函数

xdebug_debug_zval函数是xdebug扩展用来显示变量类型,引用计数及是否引用等信息的函数。一个例子:

$a = 'phppan';
xdebug_debug_zval('a');

输出:

a:
(refcount=1, is_ref=0),string 'phppan' (length=6)

xdebug_debug_zval函数与PHP自带的debug_zval_dump函数相比,显示的信息更加详情具体。除了引用计数和变量类型外,它还多了is_ref和变量的长度等额外的信息。 同样,它也支持多参数。如下代码:

$a = 'phppan';
$b = 'martin';
xdebug_debug_zval('a', 'b');

输出:

a:
(refcount=1, is_ref=0),string 'phppan' (length=6)
b:
(refcount=1, is_ref=0),string 'martin' (length=6)

xdebug_debug_zval函数传递的参数是变量名,是一个字符串。

在/ext/xdebug/xdebug.c文件中我们可以找到此函数的具体实现代码。从其代码可知:它是取 EG(active_symbol_table)中的变量容器zval相关信息显示。

以扩展的方式自定义函数

上面的两种方法都是已有的函数,如果这些不能满足需求,那么自己写吧。虽然复杂一些,但是如果自己能写出来,在技术上,在对PHP的理解上会有较大的进步。 另外,tipi项目中会有相关函数。