473,387 Members | 1,504 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,387 software developers and data experts.

possible bug with recursive array references

Hello,

I am using PHP 5.0.4 with Apache 2, on WinXP Pro. This behavior
appears to be fundamental however, and should not be affected by
platform.

It would seem that there is some kind of bug in the process that
creates the reference when it is being assigned to an array element
within itself. If it is already referenced, it just assigns the
existing reference and avoids the problem.

As I was reading the documentation about references, I noticed the
warning about "complex arrays". Here is what it says:

----- begin PHP docs -----
Complex arrays are sometimes rather copied than referenced. Thus
following example will not work as expected. Example 21-3. References
with complex arrays

<?php
$top = array(
'A' => array(),
'B' => array(
'B_b' => array(),
),
);

$top['A']['parent'] = &$top;
$top['B']['parent'] = &$top;
$top['B']['B_b']['data'] = 'test';
print_r($top['A']['parent']['B']['B_b']); // array()
?>
----- end PHP docs -----

So I decided to play around with this, and sure enough I got the same
results. But after making a few changes, I discovered that the
behavior is caused by recursively assigning the reference, and not due
to the array structure itself. Consider this example code:

<?php
$top = array( 'X' => 1, 'Y' => 1, 'Z' => 0 );
$top['Y'] = &$top;
$top['X'] = &$top;
$top['Z'] = 4;

echo "X = ", var_dump( $top['X']['Z'] );
echo "Y = ", var_dump( $top['Y']['Z'] );
echo "Z = ", var_dump( $top['Z'] );
?>

The results show:

X = int(0)
Y = int(4)
Z = int(4)

The result for X still has the original value. This would seem to
agree with the orginal statement in the PHP docs. But, if you reverse
the order of the reference assignments like this:

$top['Y'] = &$top;
$top['X'] = &$top;
$top['Z'] = 4;

Then, the result for Y has the original value.

X = int(4)
Y = int(0)
Z = int(4)

Furthermore, if you assign some arbitrary variable a reference to $top
before doing anything else...

$z = &$top;

The output appears to be "correct" now:

X = int(4)
Y = int(4)
Z = int(4)

Looking at the var_dump of the actual resulting array struct reveals
that where the reference is being assigned matches the contents of the
array at *that point in time* up until the next recursive reference
assignment. At that point $top branched off, leaving the first one
pointing to the previous instance. So it would appear that it is
actually a fractal array structure :) Each member that gets another
ref to $top adds another fractal generation to the var_dump.

But nonetheless, assigning a reference to a separate variable stops the
branching for all subsequent recursive reference assignments. So it
appears that assigning a reference to an element within itself like
that does not correctly create the reference, unless the reference was
already created.

Another way to demonstrate this is to compare the output of these two
scripts:

<?php
$top = array( 'W' => 1, 'X' => 1, 'Y' => 1, 'Z' => 0 );
$top['WW'] = 'wwwww'; $top['W'] = &$top; unset ( $top['WW'] );
$top['XX'] = 'xxxxx'; $top['X'] = &$top; unset ( $top['XX'] );
$top['YY'] = 'yyyyy'; $top['Y'] = &$top; unset ( $top['YY'] );
$top['Z'] = 4;
var_dump( $top );
?>

<?php
$top_t = array( 'W' => 1, 'X' => 1, 'Y' => 1, 'Z' => 0 );
$top_t['WW'] = 'wwwww'; $top_w = $top_t; $top_w['W'] = &$top_w; unset (
$top_w['WW'] );
$top_w['XX'] = 'xxxxx'; $top_x = $top_w; $top_x['X'] = &$top_x; unset (
$top_x['XX'] );
$top_x['YY'] = 'yyyyy'; $top_y = $top_x; $top_y['Y'] = &$top_y; unset (
$top_y['YY'] );
var_dump( $top_y );
?>

Basically, the output is the same, except that in the first one, the
dump of $top['Y']['Y'] is shorted to "*RECURSION*" but not in the
second.

Now compare the output of these two scripts:

<?php
for ( $i = 0; $i < 10; $i ++ ) $top[$i] = &$top;
$top['A'] = 'AAAAA'; var_dump( $top );
?>

<?php
$z = &$top;
for ( $i = 0; $i < 10; $i ++ ) $top[$i] = &$top;
$top['A'] = 'AAAAA'; var_dump( $top );
?>

The only difference is the reference assignment at the beginning of the
second one. But the results differ vastly. The first outputs over
157457 lines, while the second only outputs about 2554 lines.

What I would like to know, is if this is actually a bug, or if this
behavior is intentional. I do not have much knowledge of how the Zend
Engine creates the references. But I find it at least somewhat
dangerous that it can have that "fractal" effect so easily. And since
it can be avoided by simply setting a reference to a separate variable,
I am convinced that something is broken (or at least VERY confusing).

The design of the language does not seem to justify this statement:

"make a direct reference assignment to the array before adding
recursive references inside it, or else the structure will branch with
each assignment"

So... any thoughts?

Thanks,
Kaptain524

Jul 17 '05 #1
2 1984
Kaptain524 wrote:
Hello,

I am using PHP 5.0.4 with Apache 2, on WinXP Pro. This behavior
appears to be fundamental however, and should not be affected by
platform.
<snip> What I would like to know, is if this is actually a bug, or if this
behavior is intentional.


If we're voting I say BUG!

Following on from the recent discussion of typing in PHP, I like the way it
uses context to cast type, but I can't see how that could be used as a
basis for justifying this kind of behaviour[1]; it just seems inconsistent.

[1] - not that I am aware of anybody actually doing so

C.

Jul 17 '05 #2
I found another workaround to "correctly" assign the recursive array
references:

<?php
function &foo( &$a ) { return $a; }

$top = array( 'X' => 1, 'Y' => 1, 'Z' => 0 );
$top['Y'] = &foo( $top );
$top['X'] = &foo( $top );
$top['Z'] = &foo( $top );

echo "X = ", var_dump( $top['X']['Z'] );
echo "Y = ", var_dump( $top['Y']['Z'] );
echo "Z = ", var_dump( $top['Z'] );
?>

Apparently, passing by reference into a function and then returning the
reference does not affect the original variable the way it does when
the reference is created directly. I think this certainly makes it
look more like a bug.

Thanks,
Kaptain524

Jul 17 '05 #3

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

9
by: peter | last post by:
Hello all, Recently I've started to refactor my code ...(I'm using python 2.3.4) I tried to add extra functionality to old functions non-intrusively. When I used a construct, which involves...
6
by: Johan Bergman | last post by:
Hi, Maybe someone can help me with this one. The following describes a somewhat simplified version of my problem, but I think it will be sufficient. I want to use class factories (virtual...
4
by: darin dimitrov | last post by:
Hello, I need help with an algoritm that given a set of "n" distinct numbers will generate all the possible permutations of fixed length "m" of these numbers WITH repetitions (a total of n^m...
9
by: Csaba Gabor | last post by:
Inside a function, I'd like to know the call stack. By this I mean that I'd like to know the function that called this one, that one's caller and so on. So I thought to do: <script...
6
by: Juha Nieminen | last post by:
Multiple inclusion of the same header file can cause the compilation to fail because of multiple definitions of the same type. That's why it's standard practice to write all headers like this: ...
1
by: rekkufa | last post by:
I am currently building a system for serializing python objects to a readable file-format, as well as creating python objects by parsing the same format. It is more or less complete except for a...
3
dlite922
by: dlite922 | last post by:
I need to get a list of employees out of a database table. I need to end up with an array of ids (primary keys) such as Array(03,9,2,5,1) The employee table has a self reference so that...
4
by: ThEoNeAnDOnLy | last post by:
I recently had an issue with my recursive project in class. Here is the code. // Recursion.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include...
3
by: from.future.import | last post by:
Hi, I encountered garbage collection behaviour that I didn't expect when using a recursive function inside another function: the definition of the inner function seems to contain a circular...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.