8000 Fix various memory leaks in allocating strings. by TysonAndre · Pull Request #918 · phpredis/phpredis · GitHub
[go: up one dir, main page]

Skip to content

Fix various memory leaks in allocating strings. #918

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 8, 2016
Merged

Fix various memory leaks in allocating strings. #918

merged 1 commit into from
Aug 8, 2016

Conversation

TysonAndre
Copy link
Contributor

The fixes are limited to what are covered by tests/TestRedis.php

Command used to detect memory leaks (Anything mentioning redis):

USE_ZEND_ALLOC=0 ZEND_DONT_UNLOAD_MODULES=1 valgrind --leak-check=full \
    php --php-ini php.ini tests/TestRedis.php
  • USE_ZEND_ALLOC uses malloc/free/etc instead of Zend's custom allocator
  • ZEND_DONT_UNLOAD_MODULES allows valgrind to print the file and line
    numbers for a shared library (this extension)
  • about valgrind: http://valgrind.org/docs/manual/quick-start.html

While the allocated memory would be cleaned up after the end of a request,
memory leaks might cause problems for long-running CLI scripts dealing
with hundreds of thousands of keys.

zval_get_string will do one of the following for a ZVAL:

  1. If it is of type IS_STRING, it will increase the refcount and return that string (Unless the string isn't refcounted)
  2. If it is not a string, it will create a new string with refcount 1 (Or a constant string which isn't refcounted)

In both cases, zend_string_release should be called on the result.

Several other places not listed in this PR should also be using zval_get_string instead of convert_to_string.

  • In the case of zend_get_parameters and convert_to_string, the code efrees the array of parameters, but doesn't free the string that was created (e.g. if a number was converted to a string, the string wouldn't be garbage collected).

The fixes are limited to what are covered by tests/TestRedis.php

Command used to detect memory leaks (Anything mentioning redis):

```bash
USE_ZEND_ALLOC=0 ZEND_DONT_UNLOAD_MODULES=1 valgrind --leak-check=full \
    php --php-ini php.ini tests/TestRedis.php
```

- USE_ZEND_ALLOC uses malloc/free/etc instead of Zend's custom allocator
- ZEND_DONT_UNLOAD_MODULES allows valgrind to print the file and line
  numbers for a shared library (this extension)
- about valgrind: http://valgrind.org/docs/manual/quick-start.html

While the allocated memory would be cleaned up after the end of a request,
memory leaks might cause problems for long-running CLI scripts dealing
with hundreds of thousands of keys.
@michael-grunder michael-grunder merged commit ac80c17 into phpredis:php7 Aug 8, 2016
@michael-grunder
Copy link
Member

This was an awesome pull request, thank you!

You're totally right about using zval_get_string in place of convert_to_string and I'll work on getting those switched as code is updated. A lot of this is my ignorance with the php7 zend framework 😺

Cheers!
Mike

} else {
add_assoc_string(&z_sub_result, key, value);
}
efree(value); // Either way, it doesn't use the original string.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does add_assoc_string duplicate value?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author
@TysonAndre TysonAndre Aug 8, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you want to avoid duplicating strings unnecessarily, use the zend_strings instead of char* : See zend_hash_add: https://php-lxr.adamharvey.name/source/xref/PHP-7.0/Zend/zend_hash.h#80
(May be missing a layer of pointers or pointer dereferencing in this example)

// if this is the only zval referring to that array
HashTable*ht = ZVAL_ARR(z_subresult); // outside the inner loop over properties, 
zend_hash_add(ht, key, value);

(This may involve incrementing ref counts if used multiple times, or it might be done automatically if used as array keys, I'm not sure)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants
0