I should have said something about a fix.  I guess the fix
would be to always unset any variable that is attempting
to be assigned by reference before doing anything else
with the variable.  Yes?  That would at least fix BC
for the example I gave (and I think Colin's example).
If $y were unset (based on the "=&" even the "&" can't
really be used) before being set, the behavior would 
have matched 4.3.

- Todd

On Thu, 2005-09-15 at 22:08 -0700, Todd Ruth wrote:
> Aha!  That was the inspiration I needed to get the right
> combination of "&"s.  The following bit of code behaves
> differently under 4.3 vs 4.4:
> 
> <?php
> function f(&$a) { return $a; }
> $x = array('a','b','c');
> foreach (array_keys($x) as $k) {
>    // I think the following line disconnects $y in 4.3
>    // but leaves $y connected in 4.4
>    $y =& f($x[$k]);
>    $z[] =& $y;
> }
> var_dump($x);
> var_dump($z);
> ?>
> 
> My guess would be that in 4.3 the engine tries to do the
> reference even though it may be dangerous.  That would
> "disconnect" $y from the previous $z[].  4.4 knows the
> reference is impossible and leaves $y connected to the
> previous $z[].  Is that analysis correct, engine gurus?
> 
> Thanks, Colin!
> 
> - Todd
> 
> On Fri, 2005-09-16 at 10:55 +1000, Colin Tucker wrote:
> > Hello again,
> > 
> > Wow, this thread generated more heat than I thought it would, I 
> > basically just wanted to know the reasoning behind making the change to 
> > PHP4, unfortunate I guess for all involved that it went downhill.  I 
> > have learned much in the past few days, at any rate.
> > 
> > As mentioned, my code actually broke following the switch to 4.4.0, in 
> > addition to logging hundreds of E_NOTICE errors.  It's taken me some 
> > time to track down where it's going wrong, but I think I've found out 
> > the culprits involved.  It's complicated, I'll try to explain it all.
> > 
> > The problem was related to components of my web app framework (which is 
> > similar to Struts, and incidently, now being phased out for a MUCH more 
> > lightweight, PHP5-based framework), in particular, an array of 
> > attributes, view helper classes and the creation of DAOs (data access 
> > objects) at runtime via XML configuration, which would look like this:
> > 
> > <daos>
> >   <dao name="dao.freight"
> >        class="FreightDAO"
> >        component="Generic/Commerce/DAO/FreightDAO.php" />
> >   <dao name="dao.customer"
> >        class="CustomerDAO"
> >        component="Generic/Commerce/DAO/CustomerDAO.php" />
> >   <dao name="dao.order.status"
> >        class="OrderStatusDAO"
> >        component="Generic/Commerce/DAO/OrderStatusDAO.php" />
> > </daos>
> > 
> > This XML would be parsed and the relevant DAO instances would be created 
> > and recorded in attribute scope for the current application module 
> > instance.  For each dao node, the following code would be called (where 
> > $daoClass and $daoComponent are extracted from the XML attributes):
> > 
> > $dao =& $this->_createDAO($daoClass,$daoComponent);
> > 
> > if ($dao)
> > {
> >     $this->module->setAttributeByReference($name,$dao);
> > }
> > 
> > Notice it assigns by reference, however I discovered that the 
> > _createDAO() method was not *returning* by reference:
> > 
> > function _createDAO($daoClass=null,$daoComponent=null)
> > {
> > 
> > // Obtain Database Object:
> > 
> >     $database =& $this->module->findDatabase();
> > 
> >     if (is_null($database))
> >     {
> >        trigger_error($this->error(ERROR_DB_COULD_NOT_OBTAIN));
> >     }
> >     else
> >     {
> > 
> >     // Obtain Database Connection:
> > 
> >        $connection =& $database->getConnection();
> > 
> >        if (is_null($connection))
> >        {
> >           trigger_error($this->error(ERROR_DB_COULD_NOT_CONNECT));
> >        }
> >        else
> >        {
> > 
> >        // Create DAO Instance:
> > 
> >           $cmp =& new ClassComponent($daoClass,$daoComponent);
> > 
> >           $dao =& $cmp->getInstance();
> > 
> >           if ($dao)
> >           {
> >              $dao->setConnectionByReference($connection);
> > 
> >              return $dao;
> >           }
> >        }
> >     }
> > 
> >     return NULL;
> > 
> > }
> > 
> > What was happening under PHP 4.4.0 is when the newly created DAO was 
> > added to the module as an attribute (setAttributeByReference), a new 
> > attribute would be created, but ALL existing DAOs in the attribute scope 
> > would become the newly added DAO, for example:
> > 
> > (create and set the dao.freight attribute):
> > 
> > attributes (array)
> > {
> >    [dao.freight] => FreightDAO Object
> > }
> > 
> > (create and set the dao.customer attribute):
> > 
> > attributes (array)
> > {
> >    [dao.freight] => CustomerDAO Object
> >    [dao.customer] => CustomerDAO Object
> > }
> > 
> > (create and set the dao.order.status attribute):
> > 
> > attributes (array)
> > {
> >    [dao.freight] => OrderStatusDAO Object
> >    [dao.customer] => OrderStatusDAO Object
> >    [dao.order.status] => OrderStatusDAO Object
> > }
> > 
> > Simply by adding the ampersand to the _createDAO() method, like so:
> > 
> > function &_createDAO($daoClass=null,$daoComponent=null)
> > {
> > }
> > 
> > ...rectified the problem (however did not make hundreds of E_NOTICE's 
> > disappear, of course ;)).
> > 
> > The question is, why did this problem not occur before 4.4.0?  Is this 
> > an example of the "memory corruption"?
> > 
> > Regards,
> > 
> > Colin.
> > 
> 

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to