0

I'm trying to debug a PHP memory leak. According to https://stackoverflow.com/a/29398380/2724978, PHP frees memory after function ends.. well, is that also valid for object functions?

My object has the following method:

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

}

Then I change to this:

function process All(){

    $this->processD(); // intensive array processing - runs fine

}

So it appears that every function is piling up on the memory. Any ideas on how can I free it?

Community
  • 1
  • 1
sigmaxf
  • 7,998
  • 15
  • 65
  • 125

1 Answers1

1

First, a clarification of terms (so that we're clear on what we mean when we say memory leak).

  • A memory leak is what happens when a program has allocated memory on the system that is no longer reachable by the program. This simply cannot happen as a direct result of your PHP code since PHP is solely responsible for managing your program's memory for you. Meaning that if a memory leak were to occur it would be a mistake made by PHP itself (the PHP memory manager) and not PHP code that you could have written. Only PHP extensions, which are written in C, and the PHP memory manager itself can leak memory. PHP code, cannot. I can assure you that the latter is exceedingly rare, if not impossible.

So according to this information, it is not possible for your PHP code to leak memory (period).

What you probably mean to say instead, is that you've either hit the user-defined PHP memory_limit or your code has a resulted in in OOM (Out of Memory) error. This is not what one would refer to as a memory leak, however. So it is crucially important that you include the actual OOM error along with your question in order to be able to decipher the problem with any degree of authority.

Because the answer you point to has to do with freeing local function variables, and the code you present as the problem, provides absolutely no indication that any local function variables are being used, it remains entirely unclear where memory is being allocated in the first place.

If I had to take a wild guess, I would say you're probably storing this array as an object property. Thus it remains in memory subject to any living reference of the object instance during that runtime.

The difference between a local variable and an instance property is that a local variable is destroyed after the function is finished. An instance property, however, is not destroyed until the object instance to which it belongs is destroyed. This doesn't happen until the last reference to that object is destroyed or you explicitly do so yourself.

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

In the above scenario the local variable $quix is always destroyed after each method call (this doesn't change whether you use a function or method, they are the same to PHP). However, the instance property $this->arr belongs to the object instance. So PHP cannot remove that from memory by itself until that instance $foo is destroyed or the script ends (implicitly destroys all memory).

Sherif
  • 11,786
  • 3
  • 32
  • 57
  • Thanks for the through explanation. Indeed I'm loading many instance properties.. they are laravel relationships which return long arrays. So I'm thinking I need to "destroy" these properties once I'm done dealing with them.. should just setting to Null solve this? – sigmaxf Oct 30 '16 at 06:10
  • Hard to say, since I'm not familiar with what a "*laravel relationship*" is, exactly, but setting it to null is one way to get rid of the array, sure. – Sherif Oct 30 '16 at 06:42