php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #75914 Memory leak when anonymous function is assigned to the class variable
Submitted: 2018-02-04 14:04 UTC Modified: 2018-02-04 16:10 UTC
From: john357smith at gmail dot com Assigned:
Status: Not a bug Package: Performance problem
PHP Version: 7.2.2 OS: Linux
Private report: No CVE-ID: None
View Add Comment Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
You can add a comment by following this link or if you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: john357smith at gmail dot com
New email:
PHP Version: OS:

 

 [2018-02-04 14:04 UTC] john357smith at gmail dot com
Description:
------------
In case an anonymous function is assigned to the class variable (doesn't matter if public, private or protected) and a new class instance is created a memory is not freed at the end. To correctly free memory you have to set a class variable to null or call a garbage collector manually. See test script.


Test script:
---------------
class TestMem
{
  public $class_var = null;

  public function __construct()
  {
    $this->class_var = function() { };
  }
}

while (true)
{
  $frame = new TestMem();
  //$frame->class_var = null;

  //echo(gc_collect_cycles()."\n");
  echo(memory_get_usage()."\n");

  usleep(10000);
}


Expected result:
----------------
A memory usage is still on the same level.

Actual result:
--------------
A memory usage is constantly increasing.

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2018-02-04 15:47 UTC] kelunik@php.net
-Status: Open +Status: Not a bug
 [2018-02-04 15:47 UTC] kelunik@php.net
There's no leak. You're creating a circular reference there. If you use gc_collect_cycles(), everything is fine.

If you remove the usleep(), you'll see that it runs totally fine even without gc_collect_cycles(). It just takes its time until the GC kicks in.
 [2018-02-04 16:06 UTC] john357smith at gmail dot com
Where in this example is defined circular reference? Anonymous function is empty and has no references anywhere. I'm aware that it is possible after "some" time a GC will free it but the problem is this is only the smallest example. The class could be (and in fact it is) much bigger in memory which leads for me to memory limit exceeded error.
 [2018-02-04 16:10 UTC] nikic@php.net
The closure contains an implicit reference to $this. You can avoid creating the cycle by using a static closure:

    $this->class_var = static function() { };

Of course, this will only work if your closure does not require access to $this.
 [2018-02-04 16:51 UTC] john357smith at gmail dot com
OK I see, thanks for an explanation.
 
PHP Copyright © 2001-2020 The PHP Group
All rights reserved.
Last updated: Mon Aug 03 10:01:24 2020 UTC