On 26.11.2016 at 12:45, Nikita Popov wrote:
> 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).
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