PHP5 zval容器与PHP7 zval容器。参考资料及;变量现在存储了吗?

PHP5 zval容器与PHP7 zval容器。参考资料及;变量现在存储了吗?,php,php-internals,Php,Php Internals,我遵循一个教程&阅读一些关于如何使用zval(zend-value)容器在PHP中存储变量的文章。这些文章中的大多数似乎都在跟踪&从有关的文档中获取信息。我对PHP的核心是如何实现zvalstruct感到好奇,因此我打开了PHP8的源代码&它看起来与那些文章或PHP.net所描述的不同。例如,在php.net中,它声明zval容器包含refcount和is_ref,但当我在PHP8中查看时,这两个都不是源代码的一部分。因此,经过一些挖掘,我发现refcount&is_ref是PHP5中zval结

我遵循一个教程&阅读一些关于如何使用zval(zend-value)容器在PHP中存储变量的文章。这些文章中的大多数似乎都在跟踪&从有关的文档中获取信息。我对PHP的核心是如何实现
zval
struct感到好奇,因此我打开了PHP8的源代码&它看起来与那些文章或PHP.net所描述的不同。例如,在php.net中,它声明
zval
容器包含
refcount
is_ref
,但当我在PHP8中查看时,这两个都不是源代码的一部分。因此,经过一些挖掘,我发现
refcount
&
is_ref
是PHP5中
zval
结构的一部分,但后来在PHP7中发生了变化,引入了性能优化,包括更好的内存管理

这是PHP5中zval的结构代码:

struct _zval_struct {
    zvalue_value value; 
    zend_uint refcount__gc;
    zend_uchar type;    
    zend_uchar is_ref__gc;
};
这是从PHP8中的PHP7开始的样子:

struct _zval_struct {
    zend_value        value;            /* value */
    union {
        uint32_t type_info;
        struct {
            ZEND_ENDIAN_LOHI_3(
                zend_uchar    type,         /* active type */
                zend_uchar    type_flags,
                union {
                    uint16_t  extra;        /* not further specified */
                } u)
        } v;
    } u1;
    union {
        uint32_t     next;                 /* hash collision chain */
        uint32_t     cache_slot;           /* cache slot (for RECV_INIT) */
        uint32_t     opline_num;           /* opline number (for FAST_CALL) */
        uint32_t     lineno;               /* line number (for ast nodes) */
        uint32_t     num_args;             /* arguments number for EX(This) */
        uint32_t     fe_pos;               /* foreach position */
        uint32_t     fe_iter_idx;          /* foreach iterator index */
        uint32_t     property_guard;       /* single property guard */
        uint32_t     constant_flags;       /* constant flags */
        uint32_t     extra;                /* not further specified */
    } u2;
};
因此,我试图找到一些关于这方面的更新/相关信息,但似乎找不到一个好的解释,其中包括一些与PHP5相比的说明,或者php.net上的文档是否仍然相关?从PHP7开始,ref计数是否不再重要,或者它现在如何处理引用。在它依赖
is_ref
来确定是应该在写入时复制,还是仅仅指向相同的
zval
容器之前。写上拷贝机制现在是如何工作的

例如:

$a = 1;
$b = $a;
这将在PHP5中有一个
zval
容器,其中
$x
$y
符号都指向该容器,如果
$a
$b
更改了值,它只会创建容器的副本,但根据我的理解,由于PHP7,它从一开始就有两个
zval
容器,因为该值是一个简单的标量类型
int
。它什么时候进行写时拷贝


我不懂C语言,这就是为什么我很难通过查看源代码来理解发生了什么,而我在网上找到的信息与PHP的当前状态不符。

@prieber,因为它与源代码不符。我懂一点C语言,但还不到能读懂所有东西的程度。但我知道的足够多,可以告诉你,文档所陈述的内容与代码中的内容是不同的。正如我在上面展示的代码,PHP中的当前代码没有refcount&is\u ref字段,所以我不确定它是如何进行ref计数的&现在引用是如何工作的如果你认为这是错误的,告诉他们-。(和下一页)可能有用。refcounting的核心思想保持不变,但是从zval转移到hold结构。是的,没错。每个变量都有一个单独的zval,与类型无关。在本例中,$a和$b都是指向同一对象的单独ZVAL。