为了避免内存泄露,需要探究php垃圾回收机制。
一 写时复制
function cow()
{
$a='仙士可'.time();
$b=$a;
$c=$a;
//这个时候内存占用相同,$b,$c都将指向$a的内存,无需额外占用
$b='仙士可1号';
//这个时候$b的数据已经改变了,无法再引用$a的内存,所以需要额外给$b开拓内存空间
$a='仙士可2号';
//$a的数据发生了变化,同样的,$c也无法引用$a了,需要给$a额外开拓内存空间
xdebug_debug_zval('a');
xdebug_debug_zval('b');
xdebug_debug_zval('c');
}
二 引用计数
function refcount()
{
$a = '仙士可'.time();
$b = $a;
$c = $a;
xdebug_debug_zval('a');
xdebug_debug_zval('b');
xdebug_debug_zval('c');
$b='仙士可2号';
xdebug_debug_zval('a');
xdebug_debug_zval('b');
echo "脚本结束\n";
}
三 引用时引用计数变化
function refcountChange()
{
$a = 'aa';
$b = &$a; //a和b绑在一起,a变成啥b就变成啥。b变成啥a就变成啥
$c = $b;
$a = 'bb';
echo $b.PHP_EOL;
$b = 'cc';
echo $a.PHP_EOL;
xdebug_debug_zval('a');
xdebug_debug_zval('b');
xdebug_debug_zval('c');
echo "脚本结束\n";
}
四 内存溢出
function oom()
{
while (1) {
$arr[] = "dededededeeddddde";
}
}
五 内存泄漏
function xieLu()
{
class A {
public $b;
public function __construct()
{
$this->a = str_repeat('A', 1024*1024);
}
public function setB(B $b)
{
$this->b = $b;
}
}
class B
{
public $a;
public function __construct()
{
$this->a = str_repeat('B', 1024*1024);
}
public function setA(A $a)
{
$this->a = $a;
}
}
while (1) {
$a = new A();
$b = new B();
$a->setB($b);
$b->setA($a);
unset($a);
unset($b);
echo memory_get_usage().PHP_EOL;
}
}
在处理内存泄露时可以使用gc_collect_cycles()。