Hi,
I have this code:
class Test
{
public $status = 'dead';
function __construct() { $this->status = 'alive'; }
function __destruct() { echo '<br>__destruct()'; }
}
$o = new Test;
function shutdown()
{
echo '<br>shutdown()';
}
register_shutdown_function('shutdown');
function obflush( $s )
{
global $o;
return $s . '<br>obflush() ' . $o->status;
}
ob_start('obflush');
Which (using PHP 5.1.4) produces this output:
shutdown()
__destruct()
obflush() alive
I have two questions:
1) I have read that the order in which the three functions are called has
changed previously and is likely to change again in future versions of PHP.
Does this mean I cannot rely on this order at all?
2) Why is $o still "alive" in obflush() even though its destructor has been
called before? The destructor having been called, I would expect global $o
to point to a no longer existing variable (thus, "null").
Greetings,
Thomas 13 2651
Thomas Mlynarczyk wrote:
Hi,
I have this code:
class Test
{
public $status = 'dead';
function __construct() { $this->status = 'alive'; }
function __destruct() { echo '<br>__destruct()'; }
}
$o = new Test;
function shutdown()
{
echo '<br>shutdown()';
}
register_shutdown_function('shutdown');
function obflush( $s )
{
global $o;
return $s . '<br>obflush() ' . $o->status;
}
ob_start('obflush');
Which (using PHP 5.1.4) produces this output:
shutdown()
__destruct()
obflush() alive
I have two questions:
1) I have read that the order in which the three functions are called has
changed previously and is likely to change again in future versions of PHP.
Does this mean I cannot rely on this order at all?
2) Why is $o still "alive" in obflush() even though its destructor has been
called before? The destructor having been called, I would expect global $o
to point to a no longer existing variable (thus, "null").
Greetings,
Thomas
It doesn't make any difference what order the functions are in - they
are only called when your code calls them directly or indirectly (i.e. a
constructor). So whatever order you call them in is the way they will
be called.
As for the variable - the object is destroyed, the destructor is called.
But that's not what's happening here. You are calling the destructor,
so it acts just like any other function.
Rather, the destructor is called implicitly during script termination or
when the variable goes out of scope. Like a constructor, you should not
be calling a destructor.
--
==================
Remove the "x" from my email address
Jerry Stuckle
JDS Computer Training Corp. js*******@attglobal.net
==================
Hi Thomas,
The order in my version of PHP5.1.6 (main/main.c:php_request_shutdown):
/* 1. Call all possible shutdown functions registered with
register_shut down_function() */
....php_call_shutdown_functions(TSRMLS_C);...
/* 2. Call all possible __destruct() functions */
....zend_call_destructors(TSRMLS_C);...
/* 3. Flush all output buffers */
....php_end_ob_buffers((zend_bool)(SG(request_info ).headers_only?0:1)
TSRMLS_CC)...
[...more steps...]
Maybe step 2 only invokes the destructor, leaving de-allocation to be
done later? I don't know for certain. Here's some more comments about
this: http://www.zend.com/lists/php-dev/200509/msg00064.html
Thomas Mlynarczyk wrote:
Hi,
I have this code:
class Test
{
public $status = 'dead';
function __construct() { $this->status = 'alive'; }
function __destruct() { echo '<br>__destruct()'; }
}
$o = new Test;
function shutdown()
{
echo '<br>shutdown()';
}
register_shutdown_function('shutdown');
function obflush( $s )
{
global $o;
return $s . '<br>obflush() ' . $o->status;
}
ob_start('obflush');
Which (using PHP 5.1.4) produces this output:
shutdown()
__destruct()
obflush() alive
I have two questions:
1) I have read that the order in which the three functions are called has
changed previously and is likely to change again in future versions of PHP.
Does this mean I cannot rely on this order at all?
2) Why is $o still "alive" in obflush() even though its destructor has been
called before? The destructor having been called, I would expect global $o
to point to a no longer existing variable (thus, "null").
Greetings,
Thomas
Also sprach Jerry Stuckle:
It doesn't make any difference what order the functions are in - they
are only called when your code calls them directly or indirectly
(i.e. a constructor). So whatever order you call them in is the way
they will be called.
But I am not /calling/ these functions - it is PHP that decides when to call
them. I am merely registering two functions and instantiating an object.
As for the variable - the object is destroyed, the destructor is
called. But that's not what's happening here. You are calling the
destructor, so it acts just like any other function.
Where am *I* calling the destructor in my code? I am merely /defining/ the
function __destruct() and I leave it up to PHP to decide when it is to be
executed.
Rather, the destructor is called implicitly during script termination
or when the variable goes out of scope. Like a constructor, you
should not be calling a destructor.
But I am not calling it! Where in my code do I have a line that says
"$o->__destruct();"?
Greetings,
Thomas
Also sprach pe*******@gmail.com:
[PHP 5.1.6:
(1) registered shutdown functions,
(2) Destructors,
(3) ob buffers]
Maybe step 2 only invokes the destructor, leaving de-allocation to be
done later?
In this case I should not rely upon the behaviour I observed? But as my
object is in global scope, it would seem more logical to me to "keep it
alive" until *after* the last of the three steps (as $GLOBALS should live
that long), in which case its destructor should not be called before.
http://www.zend.com/lists/php-dev/200509/msg00064.html
Thank you for this link. I think, the behaviour described there refers to an
older version (PHP 5.0.5) in which the destructors were called *before* the
shutdown functions. So it does not explain why I should be able to access an
object after its destructor has been called.
Greetings,
Thomas
Thomas Mlynarczyk wrote:
Also sprach Jerry Stuckle:
>>It doesn't make any difference what order the functions are in - they are only called when your code calls them directly or indirectly (i.e. a constructor). So whatever order you call them in is the way they will be called.
But I am not /calling/ these functions - it is PHP that decides when to call
them. I am merely registering two functions and instantiating an object.
>>As for the variable - the object is destroyed, the destructor is called. But that's not what's happening here. You are calling the destructor, so it acts just like any other function.
Where am *I* calling the destructor in my code? I am merely /defining/ the
function __destruct() and I leave it up to PHP to decide when it is to be
executed.
>>Rather, the destructor is called implicitly during script termination or when the variable goes out of scope. Like a constructor, you should not be calling a destructor.
But I am not calling it! Where in my code do I have a line that says
"$o->__destruct();"?
Greetings,
Thomas
Oops, I misread your code and your post.
No, you cannot rely on the order in which things are cleaned up. It is
always subject to change.
This is no different than C++, Java or any other OO languages. The
order in which things are cleaned up is never guaranteed.
--
==================
Remove the "x" from my email address
Jerry Stuckle
JDS Computer Training Corp. js*******@attglobal.net
==================
Also sprach Jerry Stuckle:
This is no different than C++, Java or any other OO languages. The
order in which things are cleaned up is never guaranteed.
But at least the order of "calling all shutdown functions", "calling all
destructors" and "calling ob buffer function" should be well-determined,
even if the order in which the destructors are called may not be guaranteed.
And this still doesn't explain why I can access an object *after* its
destructor has been called. Strange...
Greetings,
Thomas
Thomas Mlynarczyk wrote:
Also sprach Jerry Stuckle:
>>This is no different than C++, Java or any other OO languages. The order in which things are cleaned up is never guaranteed.
But at least the order of "calling all shutdown functions", "calling all
destructors" and "calling ob buffer function" should be well-determined,
even if the order in which the destructors are called may not be guaranteed.
And this still doesn't explain why I can access an object *after* its
destructor has been called. Strange...
Greetings,
Thomas
Thomas,
No, those are all undefined.
And you can still access the object because its reference still points
to the object. PHP will destroy the object, but will not alter the
reference to the object. There is no need to - the reference will be
destroyed soon, anyway.
Destructors are meant to clean up the object itself - i.e. for a class
which access a database you could want to close the database connection.
It's never a good idea to have a destructor depend on the state of
another object which itself may be destroyed. The same is true when you
register a shutdown function - that function should not depend on the
state of any objects.
If you must do this, you need to change the destructor in your Test
object to set the state to invalid.
But that also doesn't mean it might not change again in the future. All
of the processing order is undefined.
--
==================
Remove the "x" from my email address
Jerry Stuckle
JDS Computer Training Corp. js*******@attglobal.net
==================
On Thu, 16 Nov 2006 21:28:48 +0100, "Thomas Mlynarczyk"
<th****@mlynarczyk-webdesign.dewrote:
>But at least the order of "calling all shutdown functions", "calling all destructors" and "calling ob buffer function" should be well-determined,
It looks, from the mailing list post from the other part of the thread, that
they have finally fixed this. It's been broken for a while, and was re-ordered
but was still broken, and now the order makes sense so long as you have quite a
recent version of PHP.
>even if the order in which the destructors are called may not be guaranteed.
>And this still doesn't explain why I can access an object *after* its destructor has been called. Strange...
The shutdown function ordering didn't make sense previously, so you were
seeing things you shouldn't have seen - objects who had their destructors
already called before the rest of the script had actually run yet.
Then again I suspect that the order of destruction of objects is still
undefined and not actually influenced by any sort of reference graph, so if you
reference other objects in destructors you're still in for an interesting time.
--
Andy Hassall :: an**@andyh.co.uk :: http://www.andyh.co.uk http://www.andyhsoftware.co.uk/space :: disk and FTP usage analysis tool
If the behavior did change in the future, you might be able to just
call flush() explicitly at the end of your script, to trigger your
output buffer callback before the global objects were finalized.
Thomas Mlynarczyk wrote:
Also sprach pe*******@gmail.com:
[PHP 5.1.6:
(1) registered shutdown functions,
(2) Destructors,
(3) ob buffers]
Maybe step 2 only invokes the destructor, leaving de-allocation to be
done later?
In this case I should not rely upon the behaviour I observed? But as my
object is in global scope, it would seem more logical to me to "keep it
alive" until *after* the last of the three steps (as $GLOBALS should live
that long), in which case its destructor should not be called before.
http://www.zend.com/lists/php-dev/200509/msg00064.html
Thank you for this link. I think, the behaviour described there refers to an
older version (PHP 5.0.5) in which the destructors were called *before* the
shutdown functions. So it does not explain why I should be able to access an
object after its destructor has been called.
Greetings,
Thomas
maybe i guess , once overload the function __destruct() , you should
destruct the object explicitly...
i havn't written a script to test this .....
"Thomas Mlynarczyk дµÀ£º
"
Hi,
I have this code:
class Test
{
public $status = 'dead';
function __construct() { $this->status = 'alive'; }
function __destruct() { echo '<br>__destruct()'; }
}
$o = new Test;
function shutdown()
{
echo '<br>shutdown()';
}
register_shutdown_function('shutdown');
function obflush( $s )
{
global $o;
return $s . '<br>obflush() ' . $o->status;
}
ob_start('obflush');
Which (using PHP 5.1.4) produces this output:
shutdown()
__destruct()
obflush() alive
I have two questions:
1) I have read that the order in which the three functions are called has
changed previously and is likely to change again in future versions of PHP.
Does this mean I cannot rely on this order at all?
2) Why is $o still "alive" in obflush() even though its destructor has been
called before? The destructor having been called, I would expect global $o
to point to a no longer existing variable (thus, "null").
Greetings,
Thomas
Also sprach Jerry Stuckle:
And you can still access the object because its reference still points
to the object. PHP will destroy the object, but will not alter the
reference to the object. There is no need to - the reference will be
destroyed soon, anyway.
So this is a bit like deleting a file on my harddisk - the space it occupied
is just marked as available, but as long as it is not physically overwritten
the file is still there?
Destructors are meant to clean up the object itself - i.e. for a class
which access a database you could want to close the database
connection. It's never a good idea to have a destructor depend on
the state of another object which itself may be destroyed. The same
is true when you register a shutdown function - that function should
not depend on the state of any objects.
In other words: I should always write my scripts to be completely
independent of the shutdown order.
Greetings,
Thomas
Also sprach Andy Hassall:
It looks, from the mailing list post from the other part of the
thread, that they have finally fixed this. It's been broken for a
while, and was re-ordered but was still broken, and now the order
makes sense so long as you have quite a recent version of PHP.
I had read somewhere that there was a discussion about calling the ob
function before the shutdown function and destructors. This would make more
sense to me, but I don't know if they actually did it in PHP 5.1.6 or 5.2.0.
The shutdown function ordering didn't make sense previously, so you
were seeing things you shouldn't have seen - objects who had their
destructors already called before the rest of the script had actually
run yet.
Yes, but the ob handler is still called last, i.e. *after* the destructors.
When I write my own error handler which "collects" error messages during
script execution and writes them to a file when the scripts ends, I must
make sure this writing occurs as the last step in my script. There seems to
be no elegant solution to this.
Greetings,
Thomas
Also sprach petersprc:
If the behavior did change in the future, you might be able to just
call flush() explicitly at the end of your script, to trigger your
output buffer callback before the global objects were finalized.
Indeed, that sounds like a possible solution. Thanks for the suggestion.
Greetings,
Thomas This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
by: j vickroy |
last post by:
Hello,
I'm trying to understand the behavior of the Python 2.3 logging module (MS
Windows 2k) with regard to RotatingFileHandler. The following script
illustrates a puzzling problem. What is...
|
by: Bill Sonia |
last post by:
I'm written a Windows Service to send e-mails on events
like OnStart, OnStop, OnShutDown using System.Web.Mail.
It works for everything but OnShutdown. My guess is that
once my send mail code is...
|
by: Allan Bredahl |
last post by:
Hi All
I am trying to construct an application that is able to cancel a machine
shutdown, reboot or logoff. And after performing some stuff to perform the
original shutdown order :...
|
by: Senthil |
last post by:
Hi,
I would like to know the code for reboot and shutdown windows xp
professional using VB.Net.
thanx
Senthil
|
by: Bill Sonia |
last post by:
I've written a Windows Service to send e-mails on events like OnStart,
OnStop, OnShutDown using System.Web.Mail. It works for everything but
OnShutdown. My guess is that for OnShutDown, once my...
|
by: Chris Tanger |
last post by:
Context:
C#
System.Net.Sockets
Socket created with constructor prarmeters Internetwork, Stream and TCP
everything else is left at the default parameters and options except linger
may be changed...
|
by: carbon_dragon |
last post by:
Ok, so here is the problem. I'm working on a headless server program
implemented as a .NET C# Console project. There is a UPS mounted to
this server (though not a windows compliant UPS). I can only...
|
by: jlee |
last post by:
I'm pretty much a newbie on mysql, and I need some help.
I am running mysql Ver 12.22 Distrib 4.0.24, for portbld-freebsd5.4
(i386) on a server hosting an active website.
The site's developer...
|
by: Phil Tusa |
last post by:
Greetings to all ....
I have a need to issue a shutdown and/or Restart Windows XP inside my
application. Any help or example code would be appreciated!
--
Phil
|
by: CloudSolutions |
last post by:
Introduction:
For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
|
by: Faith0G |
last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
|
by: isladogs |
last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM).
In this session, we are pleased to welcome former...
|
by: ryjfgjl |
last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
|
by: aa123db |
last post by:
Variable and constants
Use var or let for variables and const fror constants.
Var foo ='bar';
Let foo ='bar';const baz ='bar';
Functions
function $name$ ($parameters$) {
}
...
|
by: ryjfgjl |
last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
|
by: ryjfgjl |
last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
|
by: emmanuelkatto |
last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud.
Please let me know.
Thanks!
Emmanuel
|
by: nemocccc |
last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
| |