当前位置: 首页 > 后端技术 > PHP

【PHP7源码解析】PHP字符串类型引用计数初探

时间:2023-03-30 01:10:52 PHP

作者:王舒背景介绍字符串类型也是我们平时使用的类型。由于字符串的特性,为了节省内存,相同的字符串变量通常共享一块内存空间,通过引用计数来标记有多个变量使用这块内存。但是经过GDB跟踪,发现并不是所有的字符串都正常操作引用计数,有正常的累加,有时0,有时1。为了一探究竟,我简单分析了一下各种赋值情况。环境条件系统版本:Ubuntu16.04.3LTSPHP版本:PHP7.1.0gdb版本:GNUgdb(Ubuntu7.11.1-0ubuntu1~16.5)7.11.11、PHP中的基本变量zval是所有变量的基础。(zend_type.hline121)其中zend_value存储具体的数据,结构如图:(zend_type.hline101)zend_value是一个union,整体占用8个字节。u1是一个union,存放了type需要的必要数据,占用4个字节。u2位是一个union,存放一些额外的数据,比如hash碰撞时的next,占用4个字节。整个zval结构体占用16个字节,支持所有类型的PHP。PHP7用这么简单巧妙的zval来存储所有类型的数据,那么一个16字节的zval怎么能存储一个不确定长度的字符串呢?2.字符串变量startup(sapi_module)inphp_cli.c第二个节点:第424行inphp_cli.cphp_module_startup(sapi_module,NULL,0)第三个节点:mainLine2123in.czend_startup(&zuf,无效的);第四个节点:zend.c中的768行zend_interned_strings_init();非常接近第五个节点:Zend_intern_known_strings(known_strings,(sizeof(known_strings)在这里打印,know_strings,可以看到这里,文件,行,函数,类,对象等,string都在这里初始化!对应声明的地址是在zend_string.h的第383行,这里没有初始化字面量值,所以这些字符串和字面量有些区别。总结也是字符串在PHP中有很多不同的情况。1.直接硬编码在代码中的字符串,在字面量表中,引用计数一直为0,直到整个脚本执行完才会被销毁。2.执行阶段计算的字符串、临时字符串、引用计数正常计算,每次引用都会递增1.当引用计数为0时,回收内存3.引用类型字符串,多个变量引用计数是在引用类型(zend_reference)上计算的,字符串被zend_referen引用ce,引用计数为1。4.特殊字符串,PHP初始化时创建的,在整个脚本执行完后会被销毁,引用计数一直为1。