博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
引用计数原则
阅读量:2305 次
发布时间:2019-05-09

本文共 1152 字,大约阅读时间需要 3 分钟。

$test = 2222222;$abc = &$test;unset($test);var_dump($abc);以上输出的值为2222222

明明已经unset了这个变量,为什么它的引用变量仍旧能取到值呢。

在我们unset变量时,实际上PHP只是从符号表里标记清除了这个变量的zval。但由于HashTable是直接存储zval而非引用存储的,所以符号表中所占用的zval内存实际上没有真正释放。

php变量存在于一个zval的变量容器中,有类型、值、是否引用(is_ref)和引用个数(refcount),只有到引用个数为0的情况下,包含类型和值的这个变量容器才会从内存中删除。

php手册中引用计数的解释为:

每个php变量存在一个叫”zval”的变量容器中。一个zval变量容器,除了包含变量的类型和值,还包括两个字节的额外信息。第一个是”is_ref”,是个bool值,用来标识这个变量是否是属于引用集合(reference set)。通过这个字节,php引擎才能把普通变量和引用变量区分开来,由于php允许用户通过使用&来使用自定义引用,zval变量容器中还有一个内部引用计数机制,来优化内存使用。第二个额外字节是”refcount”,用以表示指向这个zval变量容器的变量(也称符号即symbol)个数。所有的符号存在一个符号表中,其中每个符号都有作用域(scope),那些主脚本(比如:通过浏览器请求的的脚本)和每个函数或者方法也都有作用域。

另外类似的解释:

在PHP的底层实现,也就是zval中,对PHP的变量类型分为了两种实现形式:对于常规类型,数据的值是直接存储在zval中的;对于对象、数组这类复杂的类型,数据的值是剥离zval,存储在内存的其他地方的,而zval中只存储了那块存储数据的内存地址。

符号表是PHP程序中变量名称和zval值对应关系的存储场所,在PHP底层实现中,是使用HashTable实现的。

在我们unset变量时,实际上PHP只是从符号表里标记清除了这个变量的zval。但由于HashTable是直接存储zval而非引用存储的,所以符号表中所占用的zval内存实际上没有真正释放。当然,在某些对符号表的操作中,可能会触发符号表的自我伸缩,这时候才会真正的对内存进行申请和释放。另外一方面,如果我们unset的是PHP的复杂类型,除了符号表中的zval外,数据的内容实际上存储在另外一块内存中。对于这种引用类型,PHP都会带有一个refcount引用计数,当zval被清除或者其他操作减少了对象的引用时,变量的引用计数会减一。而如果引用计数为零,则表示变量已经不在PHP程序中被使用了。而对于这类变量,PHP的垃圾回收机制会进行回收并释放那一块的内存。

转载地址:http://qksib.baihongyu.com/

你可能感兴趣的文章
启动vsftpd的问题---500 OOPS
查看>>
ubuntu lamp的部署
查看>>
CAS简单实例
查看>>
CAS结合openldap
查看>>
数据库基础知识
查看>>
Spring事务管理
查看>>
乐观锁-CAS
查看>>
Socket学习
查看>>
Hive几种数据导入方式
查看>>
最大子数组
查看>>
在二叉树中找出和为某一值的所有路径
查看>>
二进制中1的个数
查看>>
数值的整数次方
查看>>
链表中倒数第k个结点
查看>>
单链表反转
查看>>
合并两个排序的链表
查看>>
树的子结构
查看>>
二叉树的层次遍历
查看>>
两个链表的第一个公共节点
查看>>
二叉树的深度
查看>>