ID:               39868
 Updated by:       [EMAIL PROTECTED]
 Reported By:      jb at ez dot no
-Status:           Open
+Status:           Assigned
 Bug Type:         Unknown/Other Function
 Operating System: Kubuntu 6.10
 PHP Version:      5.2.0
-Assigned To:      
+Assigned To:      derick


Previous Comments:
------------------------------------------------------------------------

[2006-12-19 11:52:00] jb at ez dot no

> Your arguments are based on wrong assumption that object
> is created in
> __construct(). This is wrong, because __construct() is
> supposed to
> initialize it, the object itself is created by "new" and
> already exists
> in __construct().
> No bug here.

I'm very aware that the constructor does not 
create/allocate the object and that the constructor is 
used for initialization. And I never claimed that it did 
so.
What I'm saying is that the constructor (ie. 
initialization) is never called (which is correct since 
there is an exception) and therefore the destructor (which 
is uninitialization) should not be called.

ie. this expression:
$a = new Master( new Child() );

would become this (using fake opcodes).

1. allocate instance of Master as $0
2. allocate instance of Child as $1
3. call $1->__construct()
4. call $0->__construct( $1 );

the end of the script would then do:
5. if not initialized $1 goto 7
6. call $1->__destruct()
7. if not initialized $0 goto 9
8. call $0->__destruct()
9. free instance $1
10. free instance $0

Since line #3 gives an exception it will never do #4, 
however the script ends and it performs the freeing of the 
objects but not the destructor of Master since it never 
called __construct.


An alternative would also be:
1. allocate instance of Child as $1
2. call $1->__construct()
3. allocate instance of Master as $0
4. call $0->__construct( $1 );

To avoid the Master object being allocated at all. 
Whichever way is chosen the __destruct() should not be 
called in any case.


If PHP is meant to work this way there is something 
seriously wrong with its design and should be fixed.


And also to demonstrate the problem with a real-life 
example, consider this PHP code:
class Master {
    public function __construct( $child ) {
        echo __CLASS__, "::__construct() [", get_class( 
$this ), "]\n";
        $this->child = $child;
    }
    public function __destruct() {
        echo __CLASS__, "::__destruct() [", get_class( 
$this ), "]\n";
        $this->child->callByMaster();
    }
}
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";
    }
    public function callByMaster() {
        echo __CLASS__, "::__callByMaster() is called [", 
get_class( $this ), "]\n";
    }
}
$a = new Master( new Child() );


You will now get a fatal error in the destruct:
Child::__construct() [Child]
Master::__destruct() [Master]

Notice: Undefined property:  Master::$child in 
construct2.php on line 9

Call Stack:
    0.0003   1. {main}() construct2.php:0
    0.0005   2. Master->__destruct() construct2.php:0

Fatal error: Call to a member function callByMaster() on a 
non-object in construct2.php on line 9

Call Stack:
    0.0003   1. {main}() construct2.php:0
    0.0005   2. Master->__destruct() construct2.php:0



Now the only way to protect against this problem is to use 
a boolean to set if __construct() was called. However that 
means that programmer must take care of issues which PHP 
itself should solve for him.

------------------------------------------------------------------------

[2006-12-19 10:56:41] [EMAIL PROTECTED]

Your arguments are based on wrong assumption that object is created in
__construct(). This is wrong, because __construct() is supposed to
initialize it, the object itself is created by "new" and already exists
in __construct().
No bug here.

------------------------------------------------------------------------

[2006-12-19 10:38:45] jb at ez dot no

I'm sorry but this is definitely not Bogus, changing back 
to Open.

------------------------------------------------------------------------

[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."

------------------------------------------------------------------------

The remainder of the comments for this report are too long. To view
the rest of the comments, please view the bug report online at
    http://bugs.php.net/39868

-- 
Edit this bug report at http://bugs.php.net/?id=39868&edit=1

Reply via email to