> For the complete documentation index, see [llms.txt](https://phper.shujuwajue.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://phper.shujuwajue.com/phpxuan-xiang-he-yun-xing-yuan-li/phpla-ji-hui-shou-ji-zhi.md).

# PHP垃圾回收机制

php中什么是垃圾?

垃圾主要是针对内存的, 如果一个对象, 并没有任何变量引用它,那这个对象就是垃圾.

为什么要清理垃圾?

* 如果php开启了很多内存空间,但是却没有销毁它.内存会一点点的被吃掉,最终导致内存溢出!
* 有人说php线程结束的时候会销毁所有的变量,关闭所有打开的句柄资源,不都是自动的吗?为什么我们还需要清理?
* 如果你写的php代码是个需要长时间执行的呢,例如弄成守护进程?

## 垃圾回收的机制

**PHP如何找到垃圾**

第一步, 从所有变量中找到垃圾

所有的变量get\_defined\_vars函数能够看到所有已经定义的变量,那意味着php本身能存储所有变量或已开辟的内存空间,具体在zend\_globals.h中struct \_zend\_executor\_globals 中看到

```
struct _zend_executor_globals {
    //略
    HashTable *active_symbol_table;//局部变量的符号表
    HashTable symbol_table;//全局变量的符号表
    //略
};
```

能看到所有的变量,这边变量会被打上视为垃圾的标签

变量本身的定义Zend/zend.h中以看到zval的定义

```
zend_uint refcount__gc; //这个用来标记有多少个变量指向它
zend_uchar is_ref__gc; //这个用来标记用引用的方式指向它
```

查看是不是垃圾就看 refcount\_\_gc 是不是为0

```php
$a = array(1);
//$b = $a;
$a[] = $a;
unset($a[1]);
//unset($a);
//$c = &$a;
//$d = &$a;
//$c = null;
//$c =1;
//unset($a);
//unset($a);
xdebug_debug_zval('a');
//var_dump(get_defined_vars());
```

> PHP中的引用是什么？
>
> * 引用不是C的指针
> * 引用允许用两个变量来指向同一个内容
> * 引用做的第二件事是用引用传递变量
> * 引用做的第三件事是引用返回

第二步.清除垃圾

找到refcount = 0的就清除,并回收内存(5.2以及以前版本)PHP5.3版本中采用了引用计数系统中的同步周期回收(Concurrent Cycle Collection in Reference Counted Systems)算法来清除 , 基本规则是这样的 ,如果引用技术在+1 ,说明变量再用,不是垃圾,如果引用技术本身为0,那就是垃圾,需要被删除, 如果引用计数-1 其为非0 的时候 将其放到某一区块标记为疑似垃圾,然后对其做很多的模拟操作,最后找到真正的垃圾(为了解决自调用$a=array(1);$a\[]=\&a这样的垃圾)

当我们存储的疑似垃圾的区域满了的时候,就会被执行清除垃圾的操作,前提是开启了垃圾回收机制,当然,默认是打开的php.ini 设置允许你修改它：zend.enable\_gc

修改配置zend.enable\_gc ，也能通过分别调用gc\_enable() 和 gc\_disable()函数来打开和关闭垃圾回收机制。调用这些函数，与修改配置项来打开或关闭垃圾回收机制的效果是一样的。你还能调用gc\_collect\_cycles()函数达到这个目的。它能强制执行周期回收。


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://phper.shujuwajue.com/phpxuan-xiang-he-yun-xing-yuan-li/phpla-ji-hui-shou-ji-zhi.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
