ID: 39868
User updated by: jb at ez dot no
Reported By: jb at ez dot no
-Status: Bogus
+Status: Open
Bug Type: Unknown/Other Function
Operating System: Kubuntu 6.10
PHP Version: 5.2.0
New Comment:
I'm sorry but this is definitely not Bogus, changing back
to Open.
Previous Comments:
------------------------------------------------------------------------
[2006-12-19 09:59:37] jb at ez dot no
> You didn't read my reply, did you?
> "Master::__construct() is called, you don't see the
> output because the
> exception is thrown just before you print it."
I did read it, and I just think you misunderstood my
explanation.
If you see in Master::__construct() there is no exception
throwing, hence this constructor cannot throw any
exceptions. The throwing is done in the
Child::__construct() (which does not inherit the Master
class) and so it will not interfere with the constructor
of the Master class.
I don't see why PHP would call the constructor then
immediately stop it before it gets to the first line of
the constructor code.
Did you try to run this through a debugger (GDB) to verify
that the constructor is actually run?
------------------------------------------------------------------------
[2006-12-19 09:32:21] [EMAIL PROTECTED]
>You don't think it is a problem that the destructor (for
>Master) is called while the constructor (for Master) is
>never called?
You didn't read my reply, did you?
"Master::__construct() is called, you don't see the output because the
exception is thrown just before you print it."
------------------------------------------------------------------------
[2006-12-19 08:28:46] jb at ez dot no
You don't think it is a problem that the destructor (for
Master) is called while the constructor (for Master) is
never called?
In this example neither the constructor or the destructor
should be called since an exception is thrown in the Child
class, ie. the new Master() expression should never be
processed.
The problem seems to be that PHP actually allocates the
object for Master and then delays the call to construct
until the parameters are prepared (which makes sense,
except the allocation). Then when the exception is thrown
PHP will cleanup all variables/objects, it then sees the
allocated object and tries the destructor,
In a good object oriented language you would never call
the destructor unless the constructor was called and was
completed 100%.
------------------------------------------------------------------------
[2006-12-18 14:46:29] [EMAIL PROTECTED]
I don't see anything wrong here.
With "$b = new Child(); $a = new Master( $b );" the second line does
not get executed, of course you won't see any of Master methods
called.
But "$a = new Master( new Child() );" is totally different case -
Master::__construct() is called, you don't see the output because the
exception is thrown just before you print it.
------------------------------------------------------------------------
[2006-12-18 14:31:19] jb at ez dot no
Description:
------------
It is possible for PHP to call the __destruct() on an
object allthough __construct() was never called. This
seems to happen when having nested object creations and
the inner one throws and exception in the constructor.
The attached reproducable code shows the problem:
Child::__construct() [Child]
Master::__destruct() [Master]
If the last line is changed to:
$b = new Child(); $a = new Master( $b );
it works of course.
In general destructors should never be called if the
constructor was not called or even if it did not finish.
Reproduce code:
---------------
class Master {
public function __construct( $child ) {
echo __CLASS__, "::__construct() [", get_class( $this ),
"]\n";
}
public function __destruct() {
echo __CLASS__, "::__destruct() [", get_class( $this ), "]\n";
}
}
class Child {
public function __construct() {
echo __CLASS__, "::__construct() [", get_class( $this ),
"]\n";
throw new Exception( "Child failure" );
}
public function __destruct() {
echo __CLASS__, "::__destruct() [", get_class( $this ), "]\n";
}
}
$a = new Master( new Child() );
Expected result:
----------------
Child::__construct() [Child]
Actual result:
--------------
Child::__construct() [Child]
Master::__destruct() [Master]
------------------------------------------------------------------------
--
Edit this bug report at http://bugs.php.net/?id=39868&edit=1