On 26.11.2016 at 12:45, Nikita Popov wrote: > 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).
Thanks for the explanation, Nikita. > 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. Indeed. At least preg_replace()'s $count parameter has the same issue. Is there already a bug report about this? -- Christoph M. Becker -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php