PHP变量管理(销毁,分配)是基于引用计数和写时复制实现的
### 引用计数
  php垃圾回收使用来引用计数的方法,php变量由zval结构体维护,zval结构体有refcount表示有多少个变量指向这个zval容器,is_ref用于区分引用变量,当unset一个变量时,会端断开变量到内存区域的链接,同时讲该区域的refcount引用计数减1,当refcount为0时,被当做垃圾,释放内存
引用计数的信息位于给具体value结构的gc中:
```c
typedef struct _zend_refcounted_h {
uint32_t refcount; /* reference counter 32-bit */
union {
struct {
ZEND_ENDIAN_LOHI_3(
zend_uchar type,
zend_uchar flags, /* used for strings & objects */
uint16_t gc_info) /* keeps GC root number (or 0) and color */
} v;
uint32_t type_info;
} u;
} zend_refcounted_h;
```
note: 并不是所有的数据类型都会用到引用计数,如long、double直接都是硬拷贝,[参考](https://www.kancloud.cn/nickbai/php7/363267)
### 写时复制
  变量复制、函数传参时并不直接硬拷贝一份value数据,而是将refcount++,变量销毁时将refcount--,等到refcount减为0时表示已经没有变量引用这个value,将它销毁;如果其中一个变量试图更改value的内容则会重新拷贝一份value修改,同时断开旧的指向,并且refcount--
### 内存溢出问题
  php5.3版本之前会有内存溢出,主要是环形引用的问题(环形引用举个例子:数组一个元素的值复制为该数组的引用);这种问题主要出现在array,object两种类型
gc机制:当refcount减1时,如果不为0且类型是IS_ARRAY、IS_OBJECT,则添加到回收池,当回收池满了,会遍历所有变量以及变量下面每一项,模拟recount减1,如果变量整个refcount为0,表示为垃圾,可以回收
### unset函数
  unset只是断开一个变量到一块内存区域的链接,同时将该区域的引用计数-1,内存是否回收主要看refcount是否为0
### 参考
- 《PHP7内核剖析》
- [php7 垃圾回收机制详解](https://segmentfault.com/a/1190000016240169)
- php
- 编译安装
- 基本概念
- 垃圾回收机制
- 生命周期
- zval底层实现
- c扩展开发
- gdb调试工具
- 自定义扩展简单demo
- 钩子函数
- 读取php.ini配置
- 数组
- 函数
- 类
- yaf扩展底层源码
- swoole扩展底层源码
- memoryGlobal内存池
- swoole协程使用记录
- 单点登录sso原理
- compser使用
- session实现机制
- c & linux
- gcc
- 指针
- 结构体,联合和位字段
- 宏定义井号说明
- printf家族函数和可变参数
- 共享函数
- 静态库和动态库
- makefile自动化构建
- 信号一
- 信号二
- inotify监控文件事件
- socket编程
- 简介
- UNIX DOMAIN
- Internet DOMAIN
- TCP/IP
- 文件IO多路复用
- 内存管理
- 进程组,会话和控制终端
- daemon守护进程
- 多进程
- 多线程
- 常用进制转换
- go
- 入门知识
- 字节和整数装换
- python
- redis
- 应用场景
- 消息队列
- 热点数据
- 扫码登录
- 订阅发布
- 次数限制
- 抢购超卖
- 持久化机制
- mysql
- 工作流程
- MyISAM和InnoDB区别
- 用户和权限管理
- 执行计划
- sql优化
- 事务和锁
- 慢查询日志
- case...when...then...end用法
- sql
- 参考
- linux
- 内核参数优化
- 防火墙设置
- docker
- docker入门知识
- 算法
- 多维数组合
- DFA算法
- 红包金额分配