php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #30823 Objects destroyed in FIFO rather LIFO.
Submitted: 2004-11-18 11:01 UTC Modified: 2005-04-22 09:34 UTC
From: richard dot quadling at bandvulc dot co dot uk Assigned: andi (profile)
Status: Not a bug Package: Class/Object related
PHP Version: 5CVS-2005-03-06 OS: *
Private report: No CVE-ID: None
 [2004-11-18 11:01 UTC] richard dot quadling at bandvulc dot co dot uk
Description:
------------
Hi.

Create Object A (a action logging class)
Create Object B (a class which allows generates logging actions).

As each method in B is called a log entry is made by using an IN and OUT method on A.

During the shutdown, the __destroy method of A is called (which closes the log), then, the __destroy method of B is called. This method has the logging code in it. This then tries to call a destroyed object.

As you cannot refer to an object until it is created, you should always destroy objects in the reverse order in which they were created.

Richard.

Reproduce code:
---------------
<?php
class A
	{
	public function __construct()
		{
		echo 'Constructing A<br />';
		}

	public function __destruct()
		{
		echo 'Destroying A<br />';
		}

	public function Logging($sLog)
		{
		echo date('r') . ' '. $sLog . '<br />';
		}
	}

class B
	{
	public function __construct()
		{
		$GLOBALS['objLogger']->Logging(__METHOD__ . ' ' . __FILE__ . ' ' . __LINE__);
		}

	public function __destruct()
		{
		$GLOBALS['objLogger']->Logging(__METHOD__ . ' ' . __FILE__ . ' ' . __LINE__);
		}

	public function Action()
		{
		$GLOBALS['objLogger']->Logging(__METHOD__ . ' ' . __FILE__ . ' ' . __LINE__);
		}
	}

$objLogger = new A();
$objAction = new B();
$objAction->Action();
?>

Expected result:
----------------
Constructing A
Thu, 18 Nov 2004 09:51:07 +0000 B::__construct D:\Data\Web Sites\Quick Scripts\public_html\PHP Bug testing\Objects destroyed FIFO.php 24
Thu, 18 Nov 2004 09:51:07 +0000 B::Action D:\Data\Web Sites\Quick Scripts\public_html\PHP Bug testing\Objects destroyed FIFO.php 34
Thu, 18 Nov 2004 09:51:07 +0000 B::__destruct D:\Data\Web Sites\Quick Scripts\public_html\PHP Bug testing\Objects destroyed FIFO.php 29
Destroying A


Actual result:
--------------
Constructing A
Thu, 18 Nov 2004 09:51:07 +0000 B::__construct D:\Data\Web Sites\Quick Scripts\public_html\PHP Bug testing\Objects destroyed FIFO.php 24
Thu, 18 Nov 2004 09:51:07 +0000 B::Action D:\Data\Web Sites\Quick Scripts\public_html\PHP Bug testing\Objects destroyed FIFO.php 34
Destroying A
Thu, 18 Nov 2004 09:51:07 +0000 B::__destruct D:\Data\Web Sites\Quick Scripts\public_html\PHP Bug testing\Objects destroyed FIFO.php 29


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2004-11-18 22:29 UTC] tony2001@php.net
Please, run this code:
<?
class a {
	function __destruct() {
		echo "destroy A\n";
	}
}

class b {
	function __destruct() {
		echo "destroy B\n";
	}
}

$a = new a;
$b = new b;
?>
and make sure that it works as you expect.
 [2004-11-19 08:46 UTC] richard dot quadling at bandvulc dot co dot uk
Nope.

The output is ...

destroy A destroy B 

Objects are destroyed in the order they are created. This is, in my opinion, bad.

I would expect ...

destroy B destroy A

(and it took me at least 2 minutes to work out why I got nothing at all - short tags!).

Richard.
 [2005-04-21 17:33 UTC] sniper@php.net
Andi, is this behaviour carved into ZE2 stone or can it be changed?

 [2005-04-22 00:34 UTC] andi@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

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.
 [2005-04-22 09:29 UTC] richard dot quadling at bandvulc dot co dot uk
Ah.

What the answer should have been is to use unset() on the object reference.

I saw a forest and forgot my chainsaw.

Sorry for wasting time.

But, I do think that unhandled objects should be destroyed LIFO.

Richard.
 [2005-04-22 09:34 UTC] richard dot quadling at bandvulc dot co dot uk
Ah. What I was looking for was this construct ...

try
	{
	$obj = new An_Object(); // Creating ALWAYS works.
	try
		{
		// do work
		}
	catch (Exception $e)
		{
		echo 'Something went quite wrong : ' . $e->getMessage() . "\n";
		}
	}
finally
	{
	unset($obj}; // No matter what, ALWAYS destroy the object.
	}

With no finally, I got tangled.

Richard.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sat Apr 27 00:01:30 2024 UTC