# exceptions in the destructor

- Thread: https://externals.io/message/21247
- Original archive: https://news-web.php.net/php.internals/21247
- Started by Daine Mamacos on 2005-12-16T14:17:54+00:00
- Messages: 12
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #21247 — Daine Mamacos — 2005-12-16T14:17:54+00:00

URL: https://externals.io/message/21247#21247

Is there any reason why one is not allowed to throw an exception in the
destructor of a class?
I mean, it makes sense, considering this is not always the final step of code,
and it is usually used for finalising things, and it would be a good idea to
know if anything goes wrong at that stage.
Otherwise is there any compromise one can use to "emulate" this feature?

Daine Mamacos.

--
random signature

---

## #21259 — Marcus Boerger — 2005-12-16T19:38:20+00:00

URL: https://externals.io/message/21247#21259 · In reply to: #21247

Hello Daine,

marcus@zaphod /usr/src/PHP_5_1 $ php -r 'class A{function __destruct(){throw new Exception("A");}} new A;'
make: `sapi/cli/php' is up to date.

Fatal error: Uncaught exception 'Exception' with message 'A' in Command line code:1
Stack trace:
#0 Command line code(1): A::__destruct()
#1 {main}
  thrown in Command line code on line 1

As the code above clearly show, exceptions can be thrown.

marcus

Friday, December 16, 2005, 3:17:54 PM, you wrote:

> Is there any reason why one is not allowed to throw an exception in the
> destructor of a class?
> I mean, it makes sense, considering this is not always the final step of code,
> and it is usually used for finalising things, and it would be a good idea to
> know if anything goes wrong at that stage.
> Otherwise is there any compromise one can use to "emulate" this feature?

> Daine Mamacos.

> --
> random signature




Best regards,
 Marcus

---

## #21283 — Daine Mamacos — 2005-12-20T13:57:28+00:00

URL: https://externals.io/message/21247#21283

I'm not trying to argue here,
I just asked a question, and you've managed to contradict your first post.

I just asked why this is the case, and if it is, is there any way I can work
WITH this functionality.

Your last post also indicates, that because the destructors are only called
after script termination, the scope of an object is global, always.
Is this true?

Also, I've called fwrite in a destructor before, so clearly not all IO is
terminated before the destructor is called.
When you refer to output facility, what are you talking about?

Many thanks
Daine Mamacos.


On Mon, 19 Dec 2005 20:16:07 +0100, Marcus Boerger wrote
> Hello Daine,
> 
>   you still don't get it. Your problem is the way php works. You 
> cannot put any output functionality in destructors because they are 
> called *after* your scipt is being terminted (to be precise after 
> the output facility has been shutdown on script termination).
> 
> This is btw a question the general php list.
> 
> marcus
> 
> Monday, December 19, 2005, 11:07:53 AM, you wrote:
> 
> > […]
doesn't work.
> 
> > […]
> 
> > […]
> 
> > […]
of code,
> > […]
idea to
> > […]
> 
> > […]
> 
> -- 
> Best regards,
>  Marcus                            mailto:mail@marcus-boerger.de


--
random signature

---

## #21285 — Alan Pinstein — 2005-12-20T16:38:34+00:00

URL: https://externals.io/message/21247#21285 · In reply to: #21283

> Your last post also indicates, that because the destructors are  
> only called
> after script termination, the scope of an object is global, always.
> Is this true?

This isn't true, at least empirically. Destructors are called when  
the GC frees the object.

For many objects, this is at script termination. But if you null out  
the ref to an object, it will occur immediately.

$a = new A();
$a = null; // destructor called just after this line

I am not certain that this should be considered *predictable*  
behavior, as the behavior of the GC is not well/publicly documented  
to my knowledge, and thus this is a reasonable question for the  
internals list.

Personally I would like to see more documentation of how GC works so  
that we as developers can depend on it a little better for OO cleanup  
activities. I have another thread going that still remains unanswered  
about how to prevent circular references to objects that deadlock the  
GC.

Alan

> Also, I've called fwrite in a destructor before, so clearly not all  
> IO is
> terminated before the destructor is called.
> When you refer to output facility, what are you talking about?
>
> Many thanks
> Daine Mamacos.
>
>
> On Mon, 19 Dec 2005 20:16:07 +0100, Marcus Boerger wrote
> > […]
> doesn't work.
> > […]
> of code,
> > […]
> idea to
> > […]
>
>
> --
> random signature

---

## #21288 — Jochem Maas — 2005-12-20T16:59:29+00:00

URL: https://externals.io/message/21247#21288 · In reply to: #21285

Alan Pinstein wrote:
> > […]
> 
> 
> This isn't true, at least empirically. Destructors are called when  the 
> GC frees the object.
> 
> For many objects, this is at script termination. But if you null out  
> the ref to an object, it will occur immediately.
> 
> $a = new A();
> $a = null; // destructor called just after this line
> 
> I am not certain that this should be considered *predictable*  behavior, 
> as the behavior of the GC is not well/publicly documented  to my 
> knowledge, and thus this is a reasonable question for the  internals list.
> 
> Personally I would like to see more documentation of how GC works so  
> that we as developers can depend on it a little better for OO cleanup  
> activities. I have another thread going that still remains unanswered  
> about how to prevent circular references to objects that deadlock the  GC.

I feel the usefulness of the dtors is undermined even more by the
'chiken/egg' problem regarding which comes first 'shutdown' or 'running the dtors';

I don't claim to have a solution or even understand the problem fully but it
does seem to me that for most of the things an average developer would think of
using object dtors for, the mechanism is unusable; and from what I understand the
'chicken/egg' problem I mentioned has been an ongoing PITA for devs!
(IIRC Wez mentioned the to-ing and fro-ing regarding this not so long ago)

Phorce be with you. (excuse me, but I have just had my annual starwars fix :-)

> 
> Alan

---

## #21289 — Daine Mamacos — 2005-12-20T17:22:31+00:00

URL: https://externals.io/message/21247#21289 · In reply to: #21285

I agree completely...
I think the GC should be better documented.
I also would like someone to tell me why exceptions cannot be called in the
destructor? Since they can't, this means the reliability of a destructor is
uncontrolled and nothing can be done to see if this completes successfully.

This in some way or another, renders them completely useless if you require
them to complete an operation and at least have the peace of mind that you
will be able to deal with errors rather than the application throwing a fatal
error.


On Tue, 20 Dec 2005 11:38:34 -0500, Alan Pinstein wrote
> > […]
> 
> This isn't true, at least empirically. Destructors are called when  
> the GC frees the object.
> 
> For many objects, this is at script termination. But if you null out 
>  the ref to an object, it will occur immediately.
> 
> $a = new A();
> $a = null; // destructor called just after this line
> 
> I am not certain that this should be considered *predictable*  
> behavior, as the behavior of the GC is not well/publicly documented  
> to my knowledge, and thus this is a reasonable question for the  
> internals list.
> 
> Personally I would like to see more documentation of how GC works so 
>  that we as developers can depend on it a little better for OO 
> cleanup  activities. I have another thread going that still remains 
> unanswered  about how to prevent circular references to objects that 
> deadlock the  GC.
> 
> Alan
> 
> > […]
> 
> -- 
> 
> 


--
random signature

---

## #21291 — Marcus Boerger — 2005-12-20T20:27:30+00:00

URL: https://externals.io/message/21247#21291 · In reply to: #21289

Hello Daine,


a) i didn't contradict myself - you obviously didn't really follow
   what i wrote

b) you can force calling the destructor by using unset() or = null;
   but only if reference count is 1.
c) exceptions are 'thrown' not called, maybe you didn't use throw new
   exception here or you were just writing a bit weired?
d) as said already several times (not only to you) exceptions *can*
   be thrown in destructors

e) this doesn't belong in internals@

regards
marcus

Tuesday, December 20, 2005, 6:22:31 PM, you wrote:

> I agree completely...
> I think the GC should be better documented.
> I also would like someone to tell me why exceptions cannot be called in the
> destructor? Since they can't, this means the reliability of a destructor is
> uncontrolled and nothing can be done to see if this completes successfully.

> This in some way or another, renders them completely useless if you require
> them to complete an operation and at least have the peace of mind that you
> will be able to deal with errors rather than the application throwing a fatal
> error.


> On Tue, 20 Dec 2005 11:38:34 -0500, Alan Pinstein wrote
> > […]


> --
> random signature




Best regards,
 Marcus

---

## #21292 — Alan Pinstein — 2005-12-20T23:44:55+00:00

URL: https://externals.io/message/21247#21292 · In reply to: #21289

> I also would like someone to tell me why exceptions cannot be  
> called in the
> destructor? Since they can't, this means the reliability of a  
> destructor is
> uncontrolled and nothing can be done to see if this completes  
> successfully.

Your question is kindof wrong... you can always throw exceptions in  
destructors. The problem is CATCHING them.

I think probably in languages with GC's that throwing [uncaught]  
exceptions in destructors is probably a bad idea, unless you DESIRE  
termination as a result, as you don't know who's calling your  
destructor. I am not positive that this is a bad idea, but I think  
so... exceptions are meant to be caught. Uncaught exceptions are  
typically considered errors, and PHP considers them fatal.

This is precisely what's happening to you. The destructor is called  
from the script termination cleanup code, outside of your program  
scope, and thus there's no try/catch to catch your exception. I  
suppose if you really want to do this just for logging, you could use:

http://us2.php.net/manual/en/function.set-exception-handler.php

But to me this seems like a bad idea.

If you have some complicated tear-down machinery that you want to do  
try/catch with, try a method like "cleanup()" in your class and call  
it surrounded by try/catch to do your cleanup when you're done with  
the resource.

Alan

---

## #21293 — Marcus Boerger — 2005-12-20T23:53:36+00:00

URL: https://externals.io/message/21247#21293 · In reply to: #21291

Hello Daine,

> a) i didn't contradict myself - you obviously didn't really follow
>    what i wrote

> b) you can force calling the destructor by using unset() or = null;
>    but only if reference count is 1.
> c) exceptions are 'thrown' not called, maybe you didn't use throw new
>    exception here or you were just writing a bit weired?
> d) as said already several times (not only to you) exceptions *can*
>    be thrown in destructors

> e) this doesn't belong in internals@

to not forget to mention: the only thing you cannot do is throwing an
exception while an exception is already pending.

regards
marcus

---

## #21294 — Daine Mamacos — 2005-12-21T00:14:15+00:00

URL: https://externals.io/message/21247#21294 · In reply to: #21291

Marcus,
I'm not trying to argue with you, I'm just after some help.
You are confusing me somewhat.
The php manual clearly states:
"Note: Attempting to throw an exception from a destructor causes a fatal error."
I'm somewhat convinced that you cannot throw an exception from a destructor,
well you can, but it gets you nowhere.

What does forcing the call of a destructor have to do with this conversation?

If you can think of a way of working around this, that would be greatly appreciated.

Anyway,
Thanks
Daine Mamacos

On Tue, 20 Dec 2005 21:27:30 +0100, Marcus Boerger wrote
> Hello Daine,
> 
> a) i didn't contradict myself - you obviously didn't really follow
>    what i wrote
> 
> b) you can force calling the destructor by using unset() or = null;
>    but only if reference count is 1.
> c) exceptions are 'thrown' not called, maybe you didn't use throw new
>    exception here or you were just writing a bit weired?
> d) as said already several times (not only to you) exceptions *can*
>    be thrown in destructors
> 
> e) this doesn't belong in internals@
> 
> regards
> marcus
> 
> Tuesday, December 20, 2005, 6:22:31 PM, you wrote:
> 
> > […]
> 
> > […]
> 
> > […]
> 
> > […]
> 
> Best regards,
>  Marcus


--
random signature

---

## #21295 — Daine Mamacos — 2005-12-21T00:20:36+00:00

URL: https://externals.io/message/21247#21295 · In reply to: #21294

I see where all this is going.
As long as the destructor is not called as part of the cleanup code, it
works fine.
Is that assumption correct?


On Wed, 21 Dec 2005 00:14:15 +0000, Daine Mamacos wrote
> Marcus,
> I'm not trying to argue with you, I'm just after some help.
> You are confusing me somewhat.
> The php manual clearly states:
> "Note: Attempting to throw an exception from a destructor causes a 
> fatal error." I'm somewhat convinced that you cannot throw an 
> exception from a destructor, well you can, but it gets you nowhere.
> 
> What does forcing the call of a destructor have to do with this conversation?
> 
> If you can think of a way of working around this, that would be 
> greatly appreciated.
> 
> Anyway,
> Thanks
> Daine Mamacos
> 
> On Tue, 20 Dec 2005 21:27:30 +0100, Marcus Boerger wrote
> > […]
> 
> --
> random signature
> 
> -- 
> 
> 


--
random signature

---

## #21296 — Marcus Boerger — 2005-12-21T00:31:42+00:00

URL: https://externals.io/message/21247#21296 · In reply to: #21295

Hello Daine,


  as far as i can tell that assumption is correct. Destructor calls are not
reliable in shutdown. That is they are at one point all called. For any
destructor that creates a new object the destructor of that new object might
not be called. Plus a bunch of other unexpected behavior.

regards
marcus

Wednesday, December 21, 2005, 1:20:36 AM, you wrote:

> I see where all this is going.
> As long as the destructor is not called as part of the cleanup code, it
> works fine.
> Is that assumption correct?


> On Wed, 21 Dec 2005 00:14:15 +0000, Daine Mamacos wrote
> > […]
