What is the rv parameter in the zend_read_property function

101 Views Asked by At

I'm using the zend_read_property to read the attribute from an object.

zend_read_property(
    scope: *mut zend_class_entry, 
    object: *mut zval, 
    name: *const c_char, 
    name_length: size_t, 
    silent: zend_bool, 
    rv: *mut zval
) -> *mut zval
zval *output, rv;

output = zend_read_property(ce, Z_OBJ_P(ZEND_THIS), ZEND_STRL("output"), ZEND_FETCH_CLASS_SILENT, &rv);

However, I don't know why it need the rv parameter. What is the purpose of this parameter?

1

There are 1 best solutions below

0
Roger Gee On

The rv parameter is an easy way to give the class's read_property handler a place to store the property value (i.e. the return value). An implementation might not readily have the property value stored as a zval, in which case it can use the rv argument and let the caller worry about the lifecycle of the zval. You can think of it like a temporary location for the property value to live.

It's important to note that the read_property handler doesn't have to use the rv argument. Ideally, you should check to see if the return value equals the address of rv, in which case you should free the rv zval in case there is a dynamic memory structure associated with it (e.g. a string or object value).

Here's a blurb from www.phpinternalsbook.com

read_property may directly return a zval owned by the object, in which case its reference count should not be modified by read_property, and the caller should not release it. Alternatively, it may return rv for temporary zvals (e.g. result of call to __get), in which case the refcount should be incremented, and the caller is responsible for releasing the value.

I've looked over some code from php-src, and I see many instances of calling zend_read_property that do not check/free the zv value as I would expect. It could be an optimization if the programmer knows that it won't ever be used by the handler in question.

It's also unclear to me whether the caller is responsible for initializing rv. I tend to think not: if the handler decides to use rv, it will ensure it is initialized and return its address. The caller should then, in the generic case, check if the return value equals rv and free it accordingly.