博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
php 变量的分配和销毁
阅读量:5816 次
发布时间:2019-06-18

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

引用计数

引用计数是指在value中增加一个字段refcount记录指向当前value的数量,变量复制、函数传参时并不直接硬拷贝一份value数据,而是将refcount++,变量销毁时将refcount--,等到refcount减为0时表示已经没有变量引用这个value,将它销毁即可。

存储结构如下:

1 typedef struct _zend_refcounted_h { 2     uint32_t         refcount;            /* reference counter 32-bit */ 3     union { 4         struct { 5             ZEND_ENDIAN_LOHI_3( 6                 zend_uchar    type, 7                 zend_uchar    flags,    /* used for strings & objects */ 8                 uint16_t      gc_info)  /* keeps GC root number (or 0) and color */ 9         } v;10         uint32_t type_info;11     } u;12 } zend_refcounted_h;

引用计数的信息位于给具体value结构的gc中,例如在字符串变量中:

1 typedef struct _zend_string     zend_string;2 struct _zend_string {3     zend_refcounted_h gc;4     zend_ulong        h;                /* hash value */5     size_t            len;6     char              val[1];7 };

写时复制

引用计数,多个变量可能指向同一个value,然后通过refcount统计引用数,这时候如果其中一个变量试图更改value的内容则会重新拷贝一份value修改,同时断开旧的指向,写时复制的机制在计算机系统中有非常广的应用,它只有在必要的时候(写)才会发生硬拷贝,可以很好的提高效率

不是所有类型都可以copy的,比如对象、资源,实时上只有string、array两种支持,与引用计数相同,也是通过zval.u1.type_flag标识value是否可复制的

3 变量回收

PHP变量的回收主要有两种:主动销毁、自动销毁。动销毁指的就是 unset。自动销毁就是PHP的自动管理机制,在return时减掉局部变量的refcount,即使没有显式的return,PHP也会自动给加上这个操作,另外一个就是写时复制时会断开原来value的指向,这时候也会检查断开后旧value的refcount。

垃圾回收

PHP变量的回收是根据refcount实现的,当unset、return时会将变量的引用计数减掉,如果refcount减到0则直接释放value,这是变量的简单gc过程

但是实际过程中出现gc无法回收导致内存泄漏的bug,先看下一个例子:

1 $a = [1];2 $a[] = &$a;3 unset($a);

可以看到,unset($a)之后由于数组中有子元素指向$a,所以refcount > 0,无法通过简单的gc机制回收,这种变量就是垃圾,垃圾回收器要处理的就是这种情况,目前垃圾只会出现在array、object两种类型中,所以只会针对这两种情况作特殊处理:当销毁一个变量时,如果发现减掉refcount后仍然大于0,且类型是IS_ARRAY、IS_OBJECT则将此value放入gc可能垃圾双向链表中,等这个链表达到一定数量后启动检查程序将所有变量检查一遍,如果确定是垃圾则销毁释放。

 

转载于:https://www.cnblogs.com/dearmrli/p/8576078.html

你可能感兴趣的文章
802.11 学习笔记
查看>>
Leetcode-Database-176-Second Highest Salary-Easy(转)
查看>>
Lua中的元表与元方法
查看>>
Servlet&jsp基础:第三部分
查看>>
延伸 -- 分类 -- 目录
查看>>
.NET ORM框架 SqlSugar4.0 功能快速预览【开源】
查看>>
Ubuntu12.04LTS安装好后是空白桌面的解决步骤(更新显卡驱动)
查看>>
poj-3696 The Luckiest number
查看>>
[Dynamic Language] Python定时任务框架
查看>>
docker生态系统
查看>>
Furure的简单介绍和使用
查看>>
CSS3 网格布局(grid layout)基础知识 - 隐式网格自己主动布局(grid-auto-rows/grid-auto-columns/grid-auto-flow)...
查看>>
构建Docker Compose服务堆栈
查看>>
最小角回归 LARS算法包的用法以及模型参数的选择(R语言 )
查看>>
CentOS7下zip解压和unzip压缩文件
查看>>
Hadoop生态圈-Kafka常用命令总结
查看>>
如何基于Redis Replication设计并实现Redis-replicator?
查看>>
Linux 环境下 PHP 扩展的编译与安装 以 mysqli 为例
查看>>
开发uniapp必备
查看>>
TPS和QPS的区别和理解
查看>>