php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #46169 destruct in wrong order with static object
Submitted: 2008-09-24 18:14 UTC Modified: 2008-10-23 12:12 UTC
Votes:5
Avg. Score:4.4 ± 0.5
Reproduced:4 of 4 (100.0%)
Same Version:3 (75.0%)
Same OS:1 (25.0%)
From: luke at cywh dot com Assigned:
Status: Not a bug Package: Scripting Engine problem
PHP Version: 5.2.6 OS: Linux
Private report: No CVE-ID: None
 [2008-09-24 18:14 UTC] luke at cywh dot com
Description:
------------
This is related to a bug that was fixed in version 5.2.0, which you 
can read about here:

http://bugs.php.net/bug.php?id=36759

Basically if you were to initiate a class, the destruct order would be 
incorrect: "C1,C2,C3,D1,D2,D3". This was corrected in 5.2.0 to be 
"C1,C2,C3,D3,D2,C1".

The problem, however, still persists if you create an object inside a 
static object. Code to recreate this issue is included in this bug 
report.

If you initiate the classes without the Registry singleton, it 
destructs properly ($c1 = new class1()...).

Testing this with 5.1.6, the destruct order is incorrect in both 
situations (as i'd expect). If you unset the objects in reverse order 
as they were created, both work correctly on 5.1.6 and 5.2.6.

So a work-around for either version is to simply track the objects and 
unset them. But if you don't do this, the destruct order is still 
incorrect if creating your objects through a singleton object.

Reproduce code:
---------------
class shorten {
	public function __construct() { print 'C:' . get_class($this) . "<br />"; }
	public function __destruct() { print 'D:' . get_class($this) . "<br />"; }	
}
class class1 extends shorten {}
class class2 extends shorten {}
class class3 extends shorten {}
class Registry {	
	static private $instance = null;
	private $registered = array();
    static public function instance() {
        if(self::$instance == null) self::$instance = new Registry();
        return self::$instance;
    }
	private function __call($name, $arguments) {
		if( ! isset($this->registered[$name]) ) $this->registered[$name] = new $name();
		return $this->registered[$name];
	}
	private function __get($name) {
		if( ! isset($this->registered[$name]) ) $this->registered[$name] = new $name();
		return $this->registered[$name];
	}
}
Registry::instance()->class1();
Registry::instance()->class2();
Registry::instance()->class3();

Expected result:
----------------
C:class1
C:class2
C:class3
D:class3
D:class2
D:class1

Actual result:
--------------
C:class1
C:class2
C:class3
D:class1
D:class2
D:class3

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2008-09-24 18:36 UTC] luke at cywh dot com
Just discovered it's not just static objects. If you create an object 
within a function in a local variable, it destructs after the function 
finishes (like it should). But if you track it in an array in the 
primary classes scope, it destructs incorrectly still. Adding the 
Registry in the results, you get:

C:Registry
C:class1
C:class2
C:class3
D:Registry
D:class1
D:class2
D:class3

But I would expect this:

C:Registry
C:class1
C:class2
C:class3
D:Registry
D:class3
D:class2
D:class1

or this?:

C:Registry
C:class1
C:class2
C:class3
D:class3
D:class2
D:class1
D:Registry

Grrr... I'm not even sure. There is no consistency. 5.1.6 was "wrong", 
but at least it was consistently wrong.
 [2008-10-23 12:12 UTC] jani@php.net
Thank you for taking the time to write to us, but this is not
a bug. Please double-check the documentation available at
http://www.php.net/manual/ and the instructions on how to report
a bug at http://bugs.php.net/how-to-report.php


 
PHP Copyright © 2001-2025 The PHP Group
All rights reserved.
Last updated: Mon Jul 28 21:00:03 2025 UTC