On Sat, Nov 26, 2016 at 12:29 PM, Christoph M. Becker <[email protected]>
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