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