php+Zval

    技术2023-03-24  122

    Zval 是 PHP 中最重要的数据结构之一(另一个比较重要的数据结构是 hash table),它包含了 PHP 中的变量值和类型的相关信息。 1,它是一个 struct,基本结构为 struct _zval_struct { // 存储变量的值 zvalue_value value; // 表示引用计数 zend_uint refcount__gc; // 变量具体的类型 zend_uchar type; // 表示是否为引用 zend_uchar is_ref__gc; }; typedef struct _zval_struct zval; 2,Zval 在内核中的工作 $a = ['string' => 'life', 'object' => new stdClass()]; xdebug_debug_zval('a'); // a:(refcount = 1, is_ref = 0) = array('string' => (refcount = 1, is_ref = 0) = 'life', 'object' => (refcount = 1, is_ref = 0) = new stdClass()); /** * zval.value = array('string' => 'life', 'object' => new stdClass()); * zval.is_ref__gc = 0; * zval.type = 'array'; * zval.refcount__gc = 1; */ 创建数组时,会创建一个 zval(与普通变量生成的 zval 非常类似,但也有很大不同,数组和对象这类复合型的变量在生成 zval 时,会为每个 key 项生成一个 zval 容器) $c = &$a['string']; xdebug_debug_zval('a'); // a:(refcount = 1, is_ref = 0) = array('string' => (refcount = 2, is_ref = 1) = 'life', 'object' => (refcount = 1, is_ref = 0) = new stdClass()); xdebug_debug_zval('c'); // c:(refcount = 2, is_ref = 1) = 'life'; 数组引用给另一个变量时,会增加 zval 中 refcount 和 is_ref 值 $b = $a['object']; xdebug_debug_zval('a'); // a:(refcount = 1, is_ref = 0) = array('string' => (refcount = 2, is_ref = 1) = 'life', 'object' => (refcount = 2, is_ref = 0) = new stdClass()); xdebug_debug_zval('b'); // b:(refcount = 2, is_ref = 0) = new stdClass(); 数组赋值给另一个变量时,会增加 zval 中 refcount 值 $d = $b; xdebug_debug_zval('b'); // b:(refcount = 3, is_ref = 0) = new stdClass(); xdebug_debug_zval('d'); // d:(refcount = 3, is_ref = 0) = new stdClass(); $c = 'new lift'; xdebug_debug_zval('a'); // a:(refcount = 1, is_ref = 0) = array('string' => (refcount = 2, is_ref = 1) = 'new lift', 'object' => (refcount = 2, is_ref = 0) = new stdClass()); xdebug_debug_zval('c'); // c:(refcount = 2, is_ref = 1) = 'new lift'; 以上 c 引用 a['string'] 的值属于使用共享 zval 的形式,当 c 改变时 refcount 和 is_ref 值不变唯有 a 和 c 的 value 值改变 unset($c); xdebug_debug_zval('a'); // a:(refcount = 1, is_ref = 0) = array('string' => (refcount = 1, is_ref = 0) = 'new lift', 'object' => (refcount = 2, is_ref = 0) = new stdClass()); unset 时,对应减少 zval 中 refcount 和 is_ref 值
    Processed: 0.008, SQL: 9