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

Reply via email to