一个php内存泄露的例子
先附上例子
<?php
class A {
public $b = null;
public $str = '';
public function __construct(B $b)
{
$this->str = str_repeat('A', 1024 * 1024);
$this->b = $b;
}
public function __destruct()
{
echo 'kill A\r\n';
}
}
class B {
public $a = null;
public $str = '';
public function __construct()
{
$this->str = str_repeat('B', 1024 * 1024);
}
public function setA(A $a)
{
$this->a = $a;
}
public function __destruct()
{
echo 'kill B\r\n';
}
}
while(1) {
$b = new B(); //先实例化一个B对象
$a = new A($b); //再实例化一个A对象,同时把B传入A中
$b->setA($a); //通过setA方法将A传入B中
unset($b);
unset($a);
echo memory_get_usage() . PHP_EOL;
sleep(1);
}
在cli模式中执行上面的代码会得到下面的输出
2335248
4432848
6530400
8627952
10725504
12823056
可以发现虽然已经unset
了变量$a
和变量$b
,但是内存使用还是在不断的增加,并且没有触发析构函数。
因为变量作为参数相互传递赋值之后,变量$a
和变量$b
的zval
结构体中refcount=2
,而unset
后refcount=1
,根据PHP的垃圾回收机制,导致这一块内存无法被释放,造成了内存泄漏。所以你可能需要手动的去释放,在unset变量a和b之前,先进行unset($a->b)
和unset($b->a)
。
在PHP5.3之前,类似的内存泄漏还有数组的循环引用。如:
$a = array('one');
$a[] = &$a;
xdebug_debug_zval('a');
PHP5.3之后采用新的同步回收算法,可将内存泄露保持在一个阈值以下。
码字很辛苦,转载请注明来自雨林寒舍的《一个php内存泄露的例子》
2018-03-09
博客
评论