Edit report at https://bugs.php.net/bug.php?id=60139&edit=1

 ID:                 60139
 Patch added by:     dmi...@php.net
 Reported by:        lbarn...@php.net
 Summary:            Anonymous functions create cycles not detected by
                     the GC
 Status:             Assigned
 Type:               Bug
 Package:            Performance problem
 PHP Version:        5.4.0beta2
 Assigned To:        dmitry
 Block user comment: N
 Private report:     N

 New Comment:

The following patch has been added/updated:

Patch Name: gc-closure.diff
Revision:   1320059056
URL:        
https://bugs.php.net/patch-display.php?bug=60139&patch=gc-closure.diff&revision=1320059056


Previous Comments:
------------------------------------------------------------------------
[2011-10-31 08:44:09] dmi...@php.net

The following patch has been added/updated:

Patch Name: gc-closure.diff
Revision:   1320050649
URL:        
https://bugs.php.net/patch-display.php?bug=60139&patch=gc-closure.diff&revision=1320050649

------------------------------------------------------------------------
[2011-10-26 10:36:24] lbarn...@php.net

Description:
------------
In the following Script 1 and Script 2, the created objects are not destructed 
until the engine shutdowns because of a reference cycle.

The objects hold a reference to an anonymous function that itself hold a 
reference to the object.

It seems that the garbage collector is unable to break the cycle.

Script 3 doesn't leak memory because the anonymous function doesn't hold a 
reference to the object.

Test script:
---------------
# Script 1 (leaks with php5.4)

<?php

class Foo
{
    public $x;

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

echo memory_get_usage(), "\n";

for ($i = 0; $i < 1000; ++$i) {
    new Foo;
}
gc_collect_cycles();

echo memory_get_usage(), "\n";
?>

# Script 2 (leaks with php5.3)

<?php

class Foo
{
    public $x;

    public function __construct() {
        $self = $this;
        $this->x = function() use ($self) {};
    }
}

echo memory_get_usage(), "\n";

for ($i = 0; $i < 1000; ++$i) {
    new Foo;
}
gc_collect_cycles();

echo memory_get_usage(), "\n";

?>

# Script 3 (no leak)

<?php

class Foo
{
    public $x;

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

function get_fun() {
    return function() {};
}

echo memory_get_usage(), "\n";

for ($i = 0; $i < 1000; ++$i) {
    new Foo;
}
gc_collect_cycles();

echo memory_get_usage(), "\n";
?>

Expected result:
----------------
Memory usage before and after is approximatel the same:

121040
121152

Actual result:
--------------
Objects are never freed and memory usage increases:

120724
417640


------------------------------------------------------------------------



-- 
Edit this bug report at https://bugs.php.net/bug.php?id=60139&edit=1

Reply via email to