• 展开微博窗口
  • QQ:52619941
  • 微信:cnmemory
  • 展开分类目录
  • 还没有账号?

Memory

一个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和变量$bzval结构体中refcount=2,而unsetrefcount=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内存泄露的例子》

评论