On Sat, Nov 26, 2016 at 12:29 PM, Christoph M. Becker <cmbecke...@gmx.de> wrote:
> On 26.11.2016 at 01:47, Thomas Hruska wrote: > > > Okay, everyone has been helpful. Thanks. I'll go with: > > > > > > zval *zprevcount = NULL; > > zend_long count; > > > > if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|z/", > > &zprevcount) == FAILURE) return; > > > > ... > > > > if (zprevcount != NULL) > > { > > count = (zend_long)PrevCount; > > > > zval_dtor(zprevcount); > > ZVAL_LONG(zprevcount, count); > > } > > > > > > Just one little thing I found in php_str_replace_common() in > > ext/standard/string.c. That particular function calls zval_ptr_dtor() > > instead of zval_dtor() on zcount. Just wondering why it does that - I'm > > thinking it has something to do with removing the ZPP call for PHP 7 and > > using the (mostly undocumented?) Z_PARAM_ZVAL_EX() macro. However, > > php_do_pcre_match() over in ext/pcre/php_pcre.c calls zval_dtor() on > > subpats but also uses the Z_PARAM_ZVAL_EX() macro in a similar fashion. > > Looking back at PHP 5.6's php_str_replace_common() shows that it > > previously called zval_dtor(). So it might also be a bug of some sort. > > zval_dtor() destroys the value; zval_ptr_dtor() decrements the refcount, > and destroys the value only if the refcount has dropped to 0. See also > <http://www.phpinternalsbook.com/zvals/memory_management.html> (which is > written for PHP 5, but is still useful). > > In your case, zval_dtor() is appropriate, as the zval has already been > separated (ZPP's /), so there can't be other references. The situation here has become a bit confusing in PHP 7. zval_dtor() is now actually the same as zval_ptr_dtor_nogc(). As such, you can use zval_dtor() on zvals with rc>1, but collectible zvals will not be added to the GC root buffer. In the vast majority of cases, you will want to use zval_ptr_dtor(). zval_dtor() / zval_ptr_dtor_nogc() are useful either as an optimization in cases where you know for certain that a value is a root, or to prevent values from being placed in the GC root buffer, in cases where this violates the memory model (e.g. this is relevant for opcache'd literals). The fact that php_pcre.c uses zval_dtor() is simply a bug, because code like $obj = new stdClass; $obj->obj = $obj; preg_match('/./', 'x', $obj); leaks. Nikita