php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #33348 Destructor order for global objects
Submitted: 2005-06-15 09:39 UTC Modified: 2005-06-16 09:05 UTC
Votes:1
Avg. Score:5.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:0 (0.0%)
Same OS:0 (0.0%)
From: feldgendler at mail dot ru Assigned:
Status: Not a bug Package: Scripting Engine problem
PHP Version: 5.0.4 OS:
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: feldgendler at mail dot ru
New email:
PHP Version: OS:

 

 [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

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2005-06-15 09:43 UTC] tony2001@php.net
Search bug DB before submitting new bugs.
See bug #30823.
 [2005-06-15 09:46 UTC] feldgendler at mail dot ru
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;
 [2005-06-15 09:47 UTC] feldgendler at mail dot ru
Sorry for the broken line in the patch above.
 [2005-06-15 09:48 UTC] feldgendler at mail dot ru
REOPEN
Please consider patching.
 [2005-06-15 09:55 UTC] tony2001@php.net
Please read what Andi one more time:

There is no predefined order in which objects are destroyed. It is
random as object id's are re-used after objects have been destroyed.
There is no way (and I don't think there should be) to change this as we
are efficiently using existing object space. You have to build your own
mechanism (which should be quite easy) in order to order certain
destruction processes.

Even with your patch destruction order is random.
Hint: try to reassign $c1 with different object and see the result.
 [2005-06-16 06:48 UTC] feldgendler at mail dot ru
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.
 [2005-06-16 09:05 UTC] derick@php.net
All things are posted to the mailinglist, no need to open them as now we need to spend time to close it again.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Fri Apr 19 15:01:28 2024 UTC