php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #36482 Garbage Collector - bug with circular references.
Submitted: 2006-02-21 20:30 UTC Modified: 2006-02-22 08:31 UTC
Votes:2
Avg. Score:5.0 ± 0.0
Reproduced:2 of 2 (100.0%)
Same Version:1 (50.0%)
Same OS:2 (100.0%)
From: K dot Londenberg at librics dot de Assigned:
Status: Not a bug Package: Scripting Engine problem
PHP Version: 5.1.2 OS: Linux 2.6.12-1-386
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: K dot Londenberg at librics dot de
New email:
PHP Version: OS:

 

 [2006-02-21 20:30 UTC] K dot Londenberg at librics dot de
Description:
------------
The PHP Garbage Collector fails to free objects which are unreachable if they contain circular references to each other.

The example script does not provoke an out of memory error, but I have some cases where a script hits the memory limit, even if there are loads of unreachable objects to be finalized. 

Sorry, but the example code has 32 lines. I guess it won't break your big repository anyway.

Compare what happens if you run the example script as it is, and what happens if you uncomment the line containing
"$bigd->subdata->subdata = $bigd;"

If you want to test this script in a PHP Engine without large memory limits, just lower the numbers.

BTW - this is a real problem and does happen quite frequently. All you need is some kind of circular reference between some objects, and everything referenced by those objects won't be cleared by the Garbage Collector until script termination.

Reproduce code:
---------------
<?php
    // This Test case demonstrates a bug where the PHP Garbage Collector fails
    // to release objects which are unreachable but contain circular references.
    
  class bigdata {
    private $data;
    public $subdata;
    public function __construct($entries) {
            $this->data = array();
            echo "Creating BIGDATA with $entries entries\n";
            if ($entries>=1000) {
                    $this->subdata = new bigdata($entries/2);    
            }
            for ($i=0;$i<$entries;$i++) { $this->data[] = $i; }
    }
        public function __destruct() {
                echo "Destroyed BIGDATA with ".count($this->data)." entries\n";
        }
    }
  echo "<PRE>";
  echo "Creating bigdata\n";flush();
  $bigd = new bigdata(1000);
  echo "Removing reference to bigdata\n";flush();
  $bigd = null;
  echo "Creating new bigdata\n";flush();
  $bigd = new bigdata(1000);
  echo "Creating circular reference. \n";flush();
  //$bigd->subdata->subdata = $bigd; // If you omit this statement, the Gargabe collector will destroy everything as it should. 
  echo "Removing all global references to bigdata\n";flush();
  $bigd = null;
  echo "Now, exiting\n";flush();
  exit; 
?>

Expected result:
----------------
<PRE>Creating bigdata
Creating BIGDATA with 1000 entries
Creating BIGDATA with 500 entries
Removing reference to bigdata
Destroyed BIGDATA with 1000 entries
Destroyed BIGDATA with 500 entries
Creating new bigdata
Creating BIGDATA with 1000 entries
Creating BIGDATA with 500 entries
Creating circular reference. 
Removing all global references to bigdata
Destroyed BIGDATA with 1000 entries
Destroyed BIGDATA with 500 entries
Now, exiting

Actual result:
--------------
<PRE>Creating bigdata
Creating BIGDATA with 1000 entries
Creating BIGDATA with 500 entries
Removing reference to bigdata
Destroyed BIGDATA with 1000 entries
Destroyed BIGDATA with 500 entries
Creating new bigdata
Creating BIGDATA with 1000 entries
Creating BIGDATA with 500 entries
Creating circular reference. 
Removing all global references to bigdata
Now, exiting
Destroyed BIGDATA with 1000 entries
Destroyed BIGDATA with 500 entries

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2006-02-21 20:32 UTC] K dot Londenberg at librics dot de
By accident, I posted the *working* version as example code. To provoke the bug, you need to uncomment the line containing "$bigd->subdata->subdata = $bigd;"
 [2006-02-21 21:26 UTC] K dot Londenberg at librics dot de
Verified with latest CVS Source Snapshot (5.1-200602211930)
of the 5.1x series:
http://snaps.php.net/php5.1-200602211930.tar.gz
Built On: Feb 21, 2006 19:30 GMT

Built with these options:
./configure --prefix=/opt/test --without-apache --disable-pdo --without-sqlite  --without-pear

php --version returns the following:

PHP 5.1.3-dev (cgi) (built: Feb 21 2006 21:14:14)
Copyright (c) 1997-2006 The PHP Group
Zend Engine v2.1.0, Copyright (c) 1998-2006 Zend Technologies
 [2006-02-22 08:31 UTC] tony2001@php.net
See bug #33595.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Fri Apr 19 13:01:30 2024 UTC