php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Doc Bug #36847 debug_backtrace() result is not unset and eats memory
Submitted: 2006-03-24 16:56 UTC Modified: 2007-08-20 12:24 UTC
Votes:1
Avg. Score:4.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:0 (0.0%)
Same OS:0 (0.0%)
From: toggg@php.net Assigned:
Status: Closed Package: Documentation problem
PHP Version: 5CVS-2006-03-24 (snap) OS: fc3
Private report: No CVE-ID:
 [2006-03-24 16:56 UTC] toggg@php.net
Description:
------------
It was originated by http://pear.php.net/bugs/bug.php?id=6788


Reproduce code:
---------------
<?php
class test
{
    var $backtrace            = null;
    function test()
    {
        $this->backtrace = debug_backtrace();
    }
}
set_time_limit(0);
for($i = 0; $i <= 10000; $i++) {
    $ret = &new test();
    unset($ret);
} 
?>

Expected result:
----------------
nothing

Actual result:
--------------
memory exhausted

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2006-03-26 01:03 UTC] tony2001@php.net
Duplicate of bug #33487.
 [2006-03-26 06:09 UTC] toggg@php.net
This not the same situation as #33487
Here, it's not a question of local variable within a method.
And we actually unset the created object.
If I do the same with $this->backtrace = str_pad(' ', 2300); then the memory is not eaten up.
This occurs only if debug_backtrace() result is affected to a property of the test object.
 [2006-04-12 11:58 UTC] dmitry@php.net
Backtrace information that is returned from debug_backtrace() contains reference to $this object. So this examle creates circular data structure.

PHP cannot free circular structures at runtime and does free them on request shutdown.

So this bug is the same as bug #33595 (recursive references leak memory).
 [2006-04-12 12:48 UTC] toggg@php.net
OK, nice, that explains the difference to php4.
unset($res) is not sufficient ... obviously,

<?php
class test
{
    var $backtrace            = null;
    function test()
    {
        $this->backtrace = debug_backtrace();
        unset($this->backtrace[0]['object']);
    }
}
set_time_limit(0);
for($i = 0; $i <= 500000; $i++) {
    $ret = &new test();
    unset($ret);
} 
?> 

does not break anymore.

However, this circular reference is due to the new 'object' returned by debug_backtrace() which is not documented.
It merits a *big* warning.

Also, it had been nice to be able to do it by __destruct() , but it's not called by unset() ...

I report back to pear , thanks !
 [2006-04-13 06:03 UTC] dmitry@php.net
__destruct() is not called because object is not destroyed (it is still referenced from inside). unset() just destroy reference to object from variable $ret;

We need add information about 'object' field into  debug_backtrace() documentation.
 [2007-08-20 12:24 UTC] vrana@php.net
'object' already documented.
 
PHP Copyright © 2001-2014 The PHP Group
All rights reserved.
Last updated: Fri Apr 18 20:01:57 2014 UTC