爲了避免內存泄露,需要探究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()。