字符串_zend_string

写时复制:

1
2
$a = 'this is string';
$b = $a;

此时,$a和$b 在内存中指向同一地址, 当修改$a或者$b 的时候, 才会复制一份, 然后对复制的这份进行修改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
146 typedef struct _zend_refcounted_h {
147 uint32_t refcount; /* reference counter 32-bit
148 php7.1中常量字符串refcount=0,依靠u来标记常量,在7.3中已经改掉了*/
149 union {
150 struct {
151 ZEND_ENDIAN_LOHI_3(
152 zend_uchar type,
153 zend_uchar flags, /* used for strings & objects
154 存储字符串的类型,例如:常量字符串2,变量字符串0 */
155 uint16_t gc_info) /* keeps GC root number (or 0) and color */
156 } v;
157 uint32_t type_info;
158 } u;
159 } zend_refcounted_h;
160
161 struct _zend_refcounted {
162 zend_refcounted_h gc;
163 };
165 // 写时复制:对于整型或者其他简单类型的,因为zval 16个字节就可以表示了,所以是直接复制的
166 // 而对于zend_string, `$a = 'string'; $b = $a;` $a和$b的zval指向的是同一个zend_string,用zend_string中的
167 // gc中的refcount进行标记,2,表示这个zeng_string被两个zval引用了,当我们修改$b的时候,就是修改$b指向的zval,
168 // $b指向zval的地址没变,但是zval的内容变了
169 // 同时原先的zend_string的gc也会修改,refcount减1
170 struct _zend_string {
171 zend_refcounted_h gc;
172 zend_ulong h; /* hash value 以空间换时间 */
173 size_t len;
174 char val[1]; // 柔性数组一定放在结构体的尾部
175 };