Skip to main content
Created with Avocode.

Secondary Navigation

  • PHP Security Center
  • Blog
  • Store
  • Downloads
    • Downloads
    • Plugins
    • MyZend Account
  • Company
    • About Zend by Perforce
    • Careers at Perforce
    • Customers
    • Partners
    • Press
  • Contact
    • Contact Us
    • Request Pricing
    • Request Support
    • Subscribe
Home
Zend

Main Navigation - Mega Menu

  • Products

    Main Navigation - Mega Menu

    • ZendPHP
      PHP Runtime and Support
    • PHP LTS
      Patches for EOL PHP
    • ZendHQ
      Must-Have Extension for ZendPHP
    • Zend Server
      PHP Application Server
  • Services

    Main Navigation - Mega Menu

    • Service Overview
    • Migration Services
    • Audits
    • CI/CD
    • Custom Consulting
    • Admin as a Service

    Services

    Innovate faster and cut risk with PHP experts from Zend Services.

    Explore Services

  • Solutions

    Main Navigation - Mega Menu

    • PHP Cloud Solutions
    • PHP Container Solutions
    • PHP Security Solutions
    • Windows Solutions
    • Hosting Provider Solutions

    Zend Solutions Cloud

    See How Zend Helps Leading Hosting Providers Keep Their Managed Sites on Secure PHP

    Read More

  • Training

    Main Navigation - Mega Menu

    • Training Overview

    Training

    Learn PHP from PHP experts with free, on-demand, and instructor led courses.

    Explore Training

  • Resources

    Main Navigation - Mega Menu

    • Explore Resources
    • Events & Webinars
    • Papers & Videos
    • Recorded Webinars
    • Blog
    Cloud Orchestration

    Orchestrating Your PHP Applications

    Watch Now
  • Support

    Main Navigation - Mega Menu

    • Explore Support
    • PHP Long-Term Support
    • Knowledgebase
    • Documentation
    • Download Software
    • Download Plugins
    • Request Support

    Support

    Submit support requests and browse self-service resources.

    Explore Support

  • Try Free
  • PHP Security Center
  • Blog
  • Store
  • Downloads

    Main Navigation - Mega Menu

    • Downloads
    • Plugins
    • MyZend Account
    • Downloads
    • Plugins
    • MyZend Account
  • Company

    Main Navigation - Mega Menu

    • About Zend by Perforce
    • Careers at Perforce
    • Customers
    • Partners
    • About Zend by Perforce
    • Careers at Perforce
    • Customers
    • Partners
  • Contact

    Main Navigation - Mega Menu

    • Contact Us
    • Request Support
    • Subscribe

TECHNICAL GUIDE

Writing PHP Extensions

Request PDF Version
Writing PHP Extensions
1. Setting up Your PHP Build Environment on Linux
2. Generating a PHP Extension Skeleton
3. Building and Installing a PHP Extension
4. Rebuilding Extensions for Production
5. Extension Skeleton File Content
6. Running PHP Extension Tests
7. Adding New Functionality
8. Basic PHP Structures
9. PHP Arrays
10. Catching Memory Leaks
11. PHP Memory Management
12. PHP References
13. Copy on Write
14. PHP Classes and Objects
15. Using OOP in our Example Extension
16. Embedding C Data into PHP Objects
17. Overriding Object Handlers
18. Answers to Common Extension Questions

10. Catching Memory Leaks

Let’s try to pass array with a value of some unexpected type: 

$ php -r ‘var_dump(test_scale([null]));’
Warning: test_scale(): unexpected argument type in Command line code on line 1
NULL
[Wed Jan 22 13:56:11 2020] Script: ‘Standard input code’
/home/dmitry/tmp/php-src/Zend/zend_hash.c(256) : Freeing 0x00007f8189c57840 (56 bytes), script=Standard
input code
=== Total 1 memory leaks detected ===

We see our expected warning and NULL result, but then we see some debug info about leaked memory from internal PHP memory debugger. Note, that this information is only available in DEBUG PHP build, and this is one of the reasons, I recommend, to use DEBUG build during development. The information above says that 56-bytes of memory allocated on line 256 of Zend/zend_hash.c was leaked. This is the body of _zend_new_array() and we may already guess where it’s called from, because we call it just once. However, in real-life we can’t be sure about the call site, and it would be great to get a back-trace of the leaked allocation. 

On Linux we may use valgrind. It’s a great tool, that can catch memory-leaks and other incorrect memory access problems (e.g. use-after-free and out-of-boundary). Valgrind emulates the program with an overridden system memory manager (malloc, free and related functions) and catches inconsistencies. 

Looking ahead, PHP uses its own memory manager and we should switch to system one, using USE_ZEND_ALLOC environment variable. It also makes sense to disable extension unloading.

$ USE_ZEND_ALLOC=0 ZEND_DONT_UNLOAD_MODULES=1 valgrind --leak-check=full \
    php -r ‘var_dump(test_scale([null]));’
...
==19882== 56 bytes in 1 blocks are definitely lost in loss record 19 of 27
==19882== at 0x483880B: malloc (vg_replace_malloc.c:309)
==19882== by 0x997CC5: __zend_malloc (zend_alloc.c:2975)
==19882== by 0x996C30: _malloc_custom (zend_alloc.c:2416)
==19882== by 0x996D6E: _emalloc (zend_alloc.c:2535)
==19882== by 0x9E13BE: _zend_new_array (zend_hash.c:256)
==19882== by 0x4849AE0: do_scale (test.c:66)
==19882== by 0x4849F69: zif_test_scale (test.c:100)
==19882== by 0xA3CE1B: ZEND_DO_ICALL_SPEC_RETVAL_USED_HANDLER (zend_vm_execute.h:1313)
==19882== by 0xA9D0E8: execute_ex (zend_vm_execute.h:53564)
==19882== by 0xAA11A0: zend_execute (zend_vm_execute.h:57664)
==19882== by 0x9B7D0B: zend_eval_stringl (zend_execute_API.c:1082)
==19882== by 0x9B7EBF: zend_eval_stringl_ex (zend_execute_API.c:1123)
...

Now we can be sure: the source of our memory-leak is a call of zend_new_array() function from our do_scale(). To fix it, we should destroy the array in case of FAILURE. 

    } else if (Z_TYPE_P(x) == IS_ARRAY) {
        zend_array *ret = zend_new_ array(zend_array_count(Z_ARR_P(x)));
        zend_ulong idx;
        zend_string *key;
        zval *val, tmp;
        ZEND_HASH_FOREACH_KEY_VAL(Z_ARR_P(x), idx, key, val) {
            if (do_scale(&tmp, val, factor) != SUCCESS) {
                zend_array_destroy(ret);
                return FAILURE;
            }
            if (key) {
                zend_hash_add(ret, key, &tmp);
            } else {
                zend_hash_index_add(ret, idx, &tmp);
            }
        } ZEND_HASH_FOREACH_END();
        RETVAL_ARR(ret);
    } else {

Don’t forget to test this. 

Valgrind is much smarter then the internal PHP memory debugger and in case you cover your extension with *.phpt regression tests, you may run all of them under valgrind. 

$ make test TESTS=”-m”

Request PDF Version

Book traversal links for 10. Catching Memory Leaks

  • ‹ 9. PHP Arrays
  • Writing PHP Extensions
  • 11. PHP Memory Management ›

Footer menu

  • Products
    • ZendPHP
    • PHP Long-Term Support
    • ZendHQ
    • Zend Server
    • Laminas Enterprise Support
    • PHP Development Tools
  • Services
    • PHP Long-Term Support
    • Migration Services
    • Audits
    • CI/CD Services
    • Custom Consulting
    • Admin as a Service
  • Free Trials and Demos
    • ZendPHP Trial
    • Zend Server Trial
    • ZendHQ Demo
  • Training
  • Resources
    • PHP Security Center
    • Papers & Videos
    • Events & Webinars
    • Recorded Webinars
    • Blog
    • Case Studies
  • Hubs
    • PHP Versions Guide
    • Developing Web Apps With PHP
    • Guide to PHP and IBM i
  • Store
  • Downloads
    • MyZend Account
    • Plugins
    • Container Registry
  • Support
    • PHP Long-term Support
    • Knowledgebase
    • Documentation
  • Contact
    • Request Pricing
    • Request Support
    • Subscribe
  • Company
    • About Zend by Perforce
    • Careers at Perforce
    • Customers
    • Partners
    • Press
Home

Zend by Perforce © Perforce Software, Inc.
Terms of Use  |  Privacy Policy | Sitemap

Social Menu

  • Facebook
  • LinkedIn
  • Twitter
  • YouTube
  • RSS
Send Feedback