Bug #75914 [Nab]: Memory leak when anonymous function is assigned to the class variable

From: Date: Sun, 04 Feb 2018 16:10:04 +0000
Subject: Bug #75914 [Nab]: Memory leak when anonymous function is assigned to the class variable
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-213802@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=75914&edit=1 ID: 75914 Updated by: nikic@php.net Reported by: john357smith at gmail dot com Summary: Memory leak when anonymous function is assigned to the class variable Status: Not a bug Type: Bug Package: Performance problem Operating System: Linux PHP Version: 7.2.2 Block user comment: N Private report: N New Comment: 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. Previous Comments: ------------------------------------------------------------------------ [2018-02-04 16:06:16] 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 15:47:37] 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 14:04:22] 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. ------------------------------------------------------------------------ -- Edit this bug report at https://bugs.php.net/bug.php?id=75914&edit=1

« previous php.bugs (#213802) next »