17

Let's consider the following code:

class a {
    public $var1;
    function disp(){
        echo $this->var1;
        }    
    }

$obj1 = new a;
echo '<br/>After instantiation into $obj1:<br/>';    
xdebug_debug_zval('obj1');  

$obj1->var1 = "Hello ";
echo '<br/><br/>After assigning "Hello" to  $obj->var1:<br/>';
$obj1->disp();

echo "<br/><br/>";  
xdebug_debug_zval('obj1');  

The output:

After instantiation into $obj1:
obj1: (refcount=1, is_ref=0)=class a { public $var1 = (refcount=2, is_ref=0)=NULL }

After assigning "Hello" to $obj->var1:
Hello

obj1: (refcount=1, is_ref=0)=class a { public $var1 = (refcount=1, is_ref=0)='Hello ' }

One by one:

After instantiation into $obj1:
obj1: (refcount=1, is_ref=0)=class a { public $var1 = (refcount=2, is_ref=0)=NULL }

Why does $obj1->var1 have refcount=2 when there is only one object of class a?

Is it because of how the new operator makes assignment? PHP does assignment with references. When instantiated with new, no symbol/variable name is associated with that instance. But, the class properties do have names. Is the recount=2 because of this?

If that is the case then a C.O.W (copy on write) has occurred with a shallow copy WRT the class instance. While the properties are still pointing to the zval's of properties created during the instantiation using new.

Now,

After assigning "Hello" to $obj->var1:
Hello

obj1: (refcount=1, is_ref=0)=class a { public $var1 = (refcount=1, is_ref=0)='Hello ' }

So, when I assign a value to the property $obj1->var1 a new zval container for that property and hence the refcount=1?

Does this mean that the zval container created during instantiation using new still lives but cannot be accessed since there is no symbol / variable name associated with it?

Please note (from xdebug: Variable Display Features):
debug_zval_dump() is different from xdebug_debug_zval().

void xdebug_debug_zval( [string varname [, ...]] )

Displays information about a variable.

This function displays structured information about one or more variables that includes its type, value and refcount information. Arrays are explored recursively with values. This function is implemented differently from PHP's debug_zval_dump() function in order to work around the problems that that function has because the variable itself is actually passed to the function. Xdebug's version is better as it uses the variable name to lookup the variable in the internal symbol table and accesses all the properties directly without having to deal with actually passing a variable to a function. The result is that the information that this function returns is much more accurate than PHP's own function for showing zval information.

UPDATE : Dec 31th 2011:

I am trying to look at how memory allocation takes place when new is used. But There are too many other things I have to do right now. I hope I will be able to post an useful update soon. Until then here are the links to code at which I was looking at :

NikiC
  • 100,734
  • 37
  • 191
  • 225
ThinkingMonkey
  • 12,539
  • 13
  • 57
  • 81
  • Maybe xdebug_debug_zval creates a (temporary) reference to the object in question? – Eugen Rieck Dec 29 '11 at 13:58
  • That came into my mind based on this [question](http://stackoverflow.com/questions/4221645/why-the-refcount-is-2-not-1) : but in xdebug's output the refcount remains 1 later. – ThinkingMonkey Dec 29 '11 at 14:07
  • 1
    I don't have a concrete answer for you but this link may help you. http://php.net/manual/en/features.gc.refcounting-basics.php – Jared Dec 29 '11 at 14:25
  • @Jrod had read that link sometime back. Nothing is available there WRT to my question. – ThinkingMonkey Dec 29 '11 at 14:32

2 Answers2

4

Adding another instantiation $obj2 = new a; increases the refcount to 3, not 4, so it's something which happens as a result of calling xdebug_debug_zval. The purpose of the xdebug function is to avoid the confusion from the passing the variable into the function and (possibly) creating an extra reference.

Unfortunately, this does not apply to the member variables; another reference is created to those zvals in order to export them. Therefore, all the caveats and confusing circumstances listed in the note on the debug_zval_dump documentation still apply for the member variables.

cmbuckley
  • 40,217
  • 9
  • 77
  • 91
  • Yes, that is what my inference was. But am not able to find substantial evidence to support it. – ThinkingMonkey Dec 29 '11 at 17:00
  • 2
    Have a look at [xdebug_var.c](https://github.com/derickr/xdebug/blob/master/xdebug_var.c): the variable exporting for object elements handles the output. – cmbuckley Dec 29 '11 at 17:20
2

I think the section "Note: Beware the refcount" on the following page explains this: http://php.net/manual/en/function.debug-zval-dump.php

It shows that the ref count increases if zend optimizes how it's passed, but then the "caveat" being when copy-on-write is invoked, returning the refcount back down to 1.

Hope that helps

Homer6
  • 15,034
  • 11
  • 61
  • 81
  • From xdebug: [Related Functions](http://xdebug.org/docs/all_functions):`debug_zval_dump()` is different from `xdebug_debug_zval()`. So I am not able to draw inference you are stating. – ThinkingMonkey Dec 29 '11 at 17:14
  • Yes, see the updated information in the question. or The link posted in my above comment. – ThinkingMonkey Dec 29 '11 at 17:25