|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2005-06-15 09:39 UTC] feldgendler at mail dot ru
Description:
------------
If several objects are created in the global scope, their destructors are called in the same order the objects were created, not in the reverse order. PHP documentation does not promise anything certain about the order in which destructors are called, but the common practice for many object-oriented languages is to call the destructors in the reverse order. This usually (though not always) is better in cases when the objects being destroyed depend on each other. I think that the order of destructor calls for global objects should be reverse compared to the order of their creation. Actually, the same is already true for function local variables.
Reproduce code:
---------------
class C1 {
function __construct() {
print "Constructing " . get_class($this) . "\n";
}
function __destruct() {
print "Destroying " . get_class($this) . "\n";
}
}
class C2 {
function __construct() {
print "Constructing " . get_class($this) . "\n";
}
function __destruct() {
print "Destroying " . get_class($this) . "\n";
}
}
$c1 = new C1();
$c2 = new C2();
Expected result:
----------------
Constructing C1
Constructing C2
Destructing C2
Destructing C1
Actual result:
--------------
Constructing C1
Constructing C2
Destructing C1
Destructing C2
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Sun Nov 30 16:00:01 2025 UTC |
The answer on that bug was "it's not a bug". Well, I agree, it's not a bug because the manual does not promise any certain order of destruction. But I know a way to make it consistent with how it's done in other object-oriented lanuages -- just apply this simple patch: --- Zend/zend_objects_API.c.orig 2005-06-15 13:59:55.000000000 +0700 +++ Zend/zend_objects_API.c 2005-06-15 13:59:57.000000000 +0700 @@ -44,7 +44,7 @@ { zend_uint i = 1; - for (i = 1; i < objects->top ; i++) { + for (i = objects->top - 1; i > 0; i--) { if (objects->object_buckets[i].valid) { struct _store_object *obj = &objects->object_buckets[i].bucket.obj;Simply reassigning $c1 won't break the destruction order because the initial size of object_buckets is 1024, and it takes 1023 more objects before object_buckets[0] is reused, but I got the idea. I didn't think about reusing the slots in the object store, that's my fault. This could be fixed by introducing a pair of references to each object_store slot ("next created" and "previous created"), maintaining these links when adding and deleting objects, and obeying this order when calling the destructors at the end. (I can write a patch that does it.) This would introduce a tiny overhead, but make the order of destruction predictable. I think that making or not making it predictable is rather a political question. I also think that it deserves a broader discussion, could you direct me to the appropriate mailing list? Or maybe this has already been discussed among PHP developers, and the current state of things is a result of that discussion. I'm reopening this bug one last time just to draw your attention to my comment because I'm not sure that you read this otherwise, sorry. Please close it.