Another Interesting Reference Issue

php.internals

Derick Rethans

21 years ago
Hello, I encountered a strange increase of the refcount with the following script: <?php error_reporting(E_ALL); $tree = array ( 1 => 'one', 2 => 'two', 3 => 'three' ); function &find_node($key, &$node) { xdebug_debug_zval('node'); $item =& $node[$key]; return $item; } $node =& find_node(3, $tree); $node = 'drie'; The xdebug_debug_zval() function looks up the given symbol in the symbol table, and it prints it's refcount/is_ref value too (unlike the debug_zval_dump() function available in PHP which actually modifies those values). Logically you expect the refcount of $node to be 2 (once through the global var $tree, and once as local variable $node. But the refcount actually seems to be 3. I've been tracing things in the engine and found the following places where the refcount of this variable is modified (file/line nos are from php 5.0-dev): Old value = 1 New value = 2 zend_send_ref_handler (execute_data=0xbfffd410, opline=0x85f5440, op_array=0x85f0b64) at /dat/dev/php/php-5.0dev/Zend/zend_execute.c:3077 3077 zend_ptr_stack_push(&EG(argument_stack), varptr); (gdb) bt #0 zend_send_ref_handler (execute_data=0xbfffd410, opline=0x85f5440, op_array=0x85f0b64) at /dat/dev/php/php-5.0dev/Zend/zend_execute.c:3077 #1 0x0831de66 in execute (op_array=0x85f0b64) at /dat/dev/php/php-5.0dev/Zend/zend_execute.c:1415 Old value = 2 New value = 3 0x0831c192 in zend_assign_to_variable_reference (result=0x0, variable_ptr_ptr=0x85f74c8, value_ptr_ptr=0x85e4b8c, Ts=0x0) at /dat/dev/php/php-5.0dev/Zend/zend_execute.c:262 262 value_ptr->refcount++; (gdb) bt #0 0x0831c192 in zend_assign_to_variable_reference (result=0x0, variable_ptr_ptr=0x85f74c8, value_ptr_ptr=0x85e4b8c, Ts=0x0) at /dat/dev/php/php-5.0dev/Zend/zend_execute.c:262 #1 0x083227d7 in zend_recv_handler (execute_data=0xbfffd1a0, opline=0x85f63bc, op_array=0x85f7a18) at /dat/dev/php/php-5.0dev/Zend/zend_execute.c:3109 #2 0x0831de66 in execute (op_array=0x85f7a18) at /dat/dev/php/php-5.0dev/Zend/zend_execute.c:1415 It does not matter if it's passed by reference or not - the value is always 3 inside the function. What is the reason for this? regards, Derick
-- Derick Rethans http://derickrethans.nl | http://ez.no | http://xdebug.org

Dmitry Stogov

21 years ago
Hi Derick, One for global $tree. One for stack. One for local $node. = 3 What is wrong? Thanks. Dmitry.

Derick Rethans

21 years ago
On Fri, 27 May 2005, Dmitry Stogov wrote:
> One for global $tree. > > One for stack. > > One for local $node. > > = 3 > > What is wrong?
I didn't say it was wrong :) I was wondering *why* it was three. I didn't know we kept a reference for it being on the stack. Do you perhaps want to divulge what the reason for this is? thanks, Derick
-- Derick Rethans http://derickrethans.nl | http://ez.no | http://xdebug.org

Dmitry Stogov

21 years ago
We need to increment refcount then put for stack, because we can lose zval. When we pass temporary vallue to function we haven't zval on caller side. But function may ignore this parameter. So it live only on stack and destroied on exit from function. Look into example: <?php function foo($a) {} $a=1; foo($a,$a+1); ?> Thanks. Dmitry.