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