-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Open
Description
Description
Method calls may cause their return value to leak if releasing EG(This) triggers GC.
The following code:
<?php
class A {
public $cycle;
public function __construct() { $this->cycle = $this; }
}
class B {
public function get() {
return new A();
}
}
$c = new B();
$objs = [];
while (gc_status()['roots']+2 < gc_status()['threshold']) {
$obj = new stdClass;
$objs[] = $obj;
}
var_dump($c->get());
Resulted in a memory leak:
Script: 'test.php'
Zend/zend_objects.c(189) : Freeing 0x00007ffff7a5c840 (56 bytes), script=test.php
=== Total 1 memory leaks detected ===
Here is what is happening:
- After returning from
get()
,$c
is released, which triggers GCA
is removed from buffer, and is not collected because it's referenced by the call stack
- After returning from
var_dump()
,zend_vm_stack_free_args()
releasesA
withzval_ptr_dtor_nogc()
, soA
is not added to the GC buffer - At this point nothing references
A
but itself, andA
is not in the GC buffer, so it leaks
I'm not sure how to fix this appart from switching to zval_ptr_dtor()
.
PHP Version
master
Operating System
No response