ID: 17959 Updated by: [EMAIL PROTECTED] Reported By: [EMAIL PROTECTED] -Status: Analyzed +Status: Open Bug Type: Scripting Engine problem Operating System: linux PHP Version: 4.2.1 Assigned To: hholzgra
Previous Comments: ------------------------------------------------------------------------ [2002-07-29 06:50:20] [EMAIL PROTECTED] <?php // Dear Php developer, // // After considering your explanation of what exactly 'global $ptr' // is i changed my code to strictly use $GLOBALS['ptr']. However, // after doing so my program still didn't function properly! // // I had to work a bit harder to come up with a simplified example // for you. I believe i have done so below. // // Please pay close attention to the notes w/in comments explaining // strange conditions that would make this sample code to work as // expected. Now I'm certain there EXISTS a serious problem with // the Php engine when processing this code. // // Thanks, // --patrick // define array we plan to navigate. $top = array ( 'name' => 'top', 'A' => array ( 'name' => 'A', 'A_a' => array ( 'name' => 'A_a', 'fn_1' => 'Aa_fn_1', 'fn_2' => 'Aa_fn_2', 'fn_3' => 'Aa_fn_3', 'A_a_1' => array ( 'name' => 'A_a_1', 'fn_1' => 'Aa1_fn_1', 'fn_2' => 'Aa1_fn_2', ), 'A_a_2' => array ( 'name' => 'A_a_2', 'fn_1' => 'Aa2_fn_1', 'fn_2' => 'Aa2_fn_2', ), ), ), ); // setup "parent references" for each of the nodes. $top['parent'] = null; $top['A']['parent'] = &$top; $top['A']['A_a']['parent'] = &$top['A']; $top['A']['A_a']['A_a_1']['parent'] = &$top['A']['A_a']; $top['A']['A_a']['A_a_2']['parent'] = &$top['A']['A_a']; //$top['A']['A_a']['A_a_1']['parent'] = &$top['A']['A_a']; // // Note! // Here if we uncomment the above line the sample code will // magically WORK! // // Why does the order of initialization matter!? And will the // code now break elsewhere? // setup our reference to $top. $ptr is what should change // on every call to change_ptr(name). $ptr = &$top; // change_ptr( name ) does the following w/some verbose // messages to display the state of variables in question. // // if ( ptr[name] ) // ptr = ptr[name]; // function change_ptr( $name ) { printf( " change_ptr($name) " ); if ( $GLOBALS['ptr'][$name] ) { // Setting up string for later printing. $before_change = sprintf( "before: \$GLOBALS['ptr']['name'] = %s", $GLOBALS['ptr']['name'] ); $GLOBALS['ptr'] = &$GLOBALS['ptr'][$name]; $after_change = sprintf( "after: \$GLOBALS['ptr']['name'] = %s", $GLOBALS['ptr']['name'] ); printf( "<font color=\"green\"><b>CHANGED</b></font>:\n" ); printf( " %s\n %s", $before_change, $after_change ); } else printf( "<font color=\"red\"><b>NO CHANGE!</b></font>" ); printf( "<br>\n" ); } ?> <pre> <? // All of the following calls should succeed and print // 'CHANGED'. However, you will notice that the last call // will fail to change $ptr to point to the 'parent' of // $top['A']['A_a']['A_a_2']. // change_ptr('A'); change_ptr('A_a'); change_ptr('A_a_1'); change_ptr('parent'); change_ptr('A_a_2'); change_ptr('parent'); ?> </pre> ------------------------------------------------------------------------ [2002-07-23 16:24:54] [EMAIL PROTECTED] think of the "global $p;" construct as a shortcut for "$p = &$GLOBALS['p'];" so by assigning a new reference you are breaking the one to the global variable so you have to explicitly assign to $GLOBALS["p"] here (marked as documentation problem) ------------------------------------------------------------------------ [2002-07-16 08:40:10] [EMAIL PROTECTED] <?php // Here is a slightly modified version of the original // post (case 3). I hope the lenght of this test-case // acceptable as i do not know of a shorter example. // // Thanks, // --patrick // define array we plan to navigate. $top = array ( 'name' => 'top', 'A' => array ( 'name' => 'A', ), 'B' => array ( 'name' => 'B', 'B_b' => array ( 'name' => 'B_b', ), ), ); // setup "parent references" for each of the nodes. $top['parent'] = null; $top['A']['parent'] = &$top; $top['B']['parent'] = &$top; $top['B']['B_b']['parent'] = &$top['B']; // setup our reference to $top. $ptr is what should change // on every call to change_ptr(name). $ptr = &$top; // $i and $iref are meant to demonstrate the inconsistency // of manipulating references w/in functions. $i = 0; $iref = &$i; // change_ptr( name ) does the following w/some verbose // messages to display the state of variables in question. // // if ( ptr[name] ) // ptr = ptr[name]; // function change_ptr( $name ) { // This case demonstrates how change_ptr() function fails // to actually change the value of a global variable $ptr. // // Essentially 'global $ptr' seems to only be local to the // function scope and modifying its value seems to have no // bearing on the global var $ptr that is of interest. // // Please note that the demonstrated behavior is not // inconsistent with how $iref is treated. global $ptr; global $iref; $iref++; printf( " change_ptr($name) " ); if ( $ptr[$name] ) { // Setting up string for later printing. $before_change = sprintf( "before: \$ptr['name'] = %s", $ptr['name'] ) . "\n " . sprintf( " \$GLOBALS['ptr']['name'] = %s", $GLOBALS['ptr']['name'] ); $ptr = &$ptr[$name]; $after_change = sprintf( "after: \$ptr['name'] = %s", $ptr['name'] ) . "\n " . sprintf( " \$GLOBALS['ptr']['name'] = %s", $GLOBALS['ptr']['name'] ); printf( "<font color=\"green\">CHANGED</font>:\n" ); printf( " %s\n %s", $before_change, $after_change ); } else printf( "<font color=\"red\">NO CHANGE!</font>" ); printf( "\n \$iref: $iref" ); printf( "\n \$GLOBALS['iref']: $iref<br>\n" ); } ?> <pre> <? // The first call to change_ptr('B') is expected to change // globally defined $ptr to become $ptr['B'], hence, the // 2nd call to the change_ptr('B') should fail since // $top['B']['B'] does not exist. change_ptr('B'); change_ptr('B'); // What is going on?? // Why didn't previous call stick? ?> </pre> ------------------------------------------------------------------------ [2002-07-13 18:29:59] [EMAIL PROTECTED] Please provide a SHORT reproducing script. Derick ------------------------------------------------------------------------ [2002-06-25 00:41:53] [EMAIL PROTECTED] <?php // // There seems to be some issues with how array references // are handled by PHP, unless, my understanding of how // array()s and references to them are supposed to work is // seriously flawed. // // Unfortunately i don't have enough time on my hands to // dig through PHP sources. // // The source below seems to be a few very simple test-cases // pointing out the bug that's caused me enough grief. // Hopefully, someone can use this information in tracking // down the bug and eventually fixing it. // // The following issues can be duplicated on both // PHP Versions 4.1.2 and 4.2.1 // // I'm not much concerned about 'Case 1' as I am about // cases 3 and 4. They seem more serious problems. // ?> <? // -- Case 1 // This case demonstrates that $top['B']['B_b']['parent'] loses // the reference to parent array! // $top = array ( 'name' => 'top', 'parent' => null, 'A' => array ( 'name' => 'A', 'parent' => &$top, ), 'B' => array ( 'name' => 'B', 'parent' => &$top, 'B_b' => array ( 'name' => 'B_b', 'parent' => &$top['B'], ), ), ); ?> <pre> case 1: top: <? foreach ( $top as $k => $v ) { printf( " $k => $v\n" ); } ?> </pre> <pre> top['A']: <? foreach ( $top['A'] as $k => $v ) { printf( " $k => $v\n" ); } ?> </pre> <pre> top['B']: <? foreach ( $top['B'] as $k => $v ) { printf( " $k => $v\n" ); } ?> </pre> <pre> top['B']['B_b']: <? foreach ( $top['B']['B_b'] as $k => $v ) { printf( " $k => $v\n" ); } // // What happened to $top['B']['B_b']['parent'] reference? // ?> </pre> <hr align="left" size="5" width="80%"> <? // -- Case 2 // This case shows a work around to above bug. // $top = array ( 'name' => 'top', //'parent' => null, 'A' => array ( 'name' => 'A', //'parent' => &$top, ), 'B' => array ( 'name' => 'B', //'parent' => &$top, 'B_b' => array ( 'name' => 'B_b', //'parent' => &$top['B'], ), ), ); $top['parent'] = null; $top['A']['parent'] = &$top; $top['B']['parent'] = &$top; $top['B']['B_b']['parent'] = &$top['B']; ?> <pre> case 2: top: <? foreach ( $top as $k => $v ) { printf( " $k => $v\n" ); } ?> </pre> <pre> top['A']: <? foreach ( $top['A'] as $k => $v ) { printf( " $k => $v\n" ); } ?> </pre> <pre> top['B']: <? foreach ( $top['B'] as $k => $v ) { printf( " $k => $v\n" ); } ?> </pre> <pre> top['B']['B_b']: <? foreach ( $top['B']['B_b'] as $k => $v ) { printf( " $k => $v\n" ); } ?> </pre> <hr align="left" size="5" width="80%"> <pre> case 3: <? // -- Case 3 // This case demonstrates how change_ptr() function fails to actually // change the value of a global variable $ptr. // // Essentially 'global $ptr' seems to only be local to the function // scope and modifying its value seems to have no bearing on the // global variable $ptr that we are interested in!! // // Please note that the demonstrated behavior is inconsistant with // how $iref is treated. // $ptr = &$top; $i = 0; $iref = &$i; function change_ptr( $name ) { global $ptr; global $iref; $iref++; printf( " change_ptr($name) " ); if ( $ptr[$name] ) { $before_change = sprintf( "before: \$ptr['name'] = %s", $ptr['name'] ) . "\n " . sprintf( " \$GLOBALS['ptr']['name'] = %s", $GLOBALS['ptr']['name'] ); $ptr = &$ptr[$name]; $after_change = sprintf( "after: \$ptr['name'] = %s", $ptr['name'] ) . "\n " . sprintf( " \$GLOBALS['ptr']['name'] = %s", $GLOBALS['ptr']['name'] ); printf( "<font color=\"green\">CHANGED</font>:\n" ); printf( " %s\n %s", $before_change, $after_change ); } else printf( "<font color=\"red\">NO CHANGE!</font>" ); printf( "\n \$iref: $iref<br>\n" ); } change_ptr('B'); change_ptr('B'); // what is going on?? Why didn't previous call stick? ?> </pre> <hr align="left" size="5" width="80%"> <pre> case 4: <? // -- Case 4 // This case shows the expected behavior of 'Case 3'. // function change_ptr2( $name ) { global $iref; $iref++; printf( " change_ptr2($name) " ); if ( $GLOBALS['ptr'][$name] ) { $before_change = sprintf( "before: \$GLOBALS['ptr']['name'] = %s", $GLOBALS['ptr']['name'] ); $GLOBALS['ptr'] = &$GLOBALS['ptr'][$name]; $after_change = sprintf( "after: \$GLOBALS['ptr']['name'] = %s", $GLOBALS['ptr']['name'] ); printf( "<font color=\"green\">CHANGED</font>:\n" ); printf( " %s\n %s", $before_change, $after_change ); } else printf( "<font color=\"red\">NO CHANGE!</font>" ); printf( "\n \$iref: $iref<br>\n" ); } change_ptr2('B'); change_ptr2('B'); // good! no change change_ptr2('B_b'); change_ptr2('parent'); // Back to $top['B'] change_ptr2('parent'); // Back to $top change_ptr2('A'); // This call will cause a problem soon! change_ptr2('parent'); change_ptr2('B'); change_ptr2('B_b'); // And just as we were doing so well ... change_ptr2('parent'); // Grrr! What happened!?!? // apparently the call change_ptr2('A') screws something up. ?> </pre> <? // ex: ai et sw=2 ts=2 ?> ------------------------------------------------------------------------ -- Edit this bug report at http://bugs.php.net/?id=17959&edit=1