是否同一对象中的方法在执行后释放内存


Does methods in the same object free memory after executed?

我正在尝试调试PHP内存泄漏。根据https://stackoverflow.com/a/29398380/2724978, PHP在函数结束后释放内存。这对对象函数也是有效的吗?

我的对象有以下方法:

function process All(){
    $this->processA(); // intensive array processing - runs fine
    $this->processB(); // intensive array processing - runs fine
    $this->processC(); // intensive array processing - runs fine
    $this->processD(); // intensive array processing - memory leak
}

然后改成:

function process All(){
    $this->processD(); // intensive array processing - runs fine
}

所以看起来每个函数都在内存上堆积。有什么办法让我解放它吗?

首先,澄清术语(以便我们清楚地了解当我们说内存泄漏时的含义)。

    内存泄漏是指当程序在系统上分配了该程序无法访问的内存时发生的情况。这种情况不可能是PHP代码的直接结果,因为PHP只负责为您管理程序的内存。这意味着如果发生内存泄漏,那将是PHP本身( PHP内存管理器)造成的错误,而不是您可以编写的PHP代码。只有用C编写的PHP扩展和PHP内存管理器本身才会泄漏内存。PHP代码,不能。我可以向你保证,后者即使不是不可能,也是极其罕见的。

因此根据此信息,PHP代码不可能泄漏内存(period)。

可能的意思是,您要么击中了用户定义的PHP memory_limit,要么您的代码导致了OOM (内存不足)错误。然而,这并不是我们所说的内存泄漏。因此,在你的问题中包含实际的OOM错误是至关重要的,以便能够以任何程度的权威来解读问题。

因为您指出的答案与释放局部函数变量有关,而您提出的问题代码完全没有指出正在使用任何局部函数变量,因此仍然完全不清楚内存首先被分配到哪里。

如果我必须大胆猜测,我会说你可能将这个数组存储为对象属性。因此,在该运行时期间,它将保留在内存中,受对象实例的任何活动引用的影响。

局部变量和实例属性的区别在于局部变量在函数结束后被销毁。但是,实例属性在其所属的对象实例被销毁之前不会被销毁。直到对该对象的最后一个引用被销毁,或者你自己显式地销毁,才会发生这种情况。

class Foo {
    protected $arr = [];
    public function bar($baz) {
        $this->arr[] = $baz; // object instance property
        $quix = $baz; // local function variable
    }
}
$foo = new Foo;
$foo->bar(1);
$foo->bar(2);
$foo->bar(3); // memory grows

在上面的场景中,局部变量$quix总是在每次方法调用之后被销毁(这不会改变你是使用函数还是方法,它们对PHP是一样的)。但是,实例属性$this->arr属于对象实例。所以PHP不能自己从内存中删除它,直到实例$foo被销毁或脚本结束(隐式地破坏所有内存)。