I have a debug build of PHP, and with that, the following script generates a memory leak:
$host = isset($_SERVER['COUCHBASE_HOST']) ? $_SERVER['COUCHBASE_HOST'] : '127.0.0.1';
|
$user = isset($_SERVER['COUCHBASE_USER']) ? $_SERVER['COUCHBASE_USER'] : 'admin';
|
$password = isset($_SERVER['COUCHBASE_PASSWORD']) ? $_SERVER['COUCHBASE_PASSWORD'] : 'pw';
|
$bucketName = 'myBucket';
|
|
// Establish username and password for bucket-access
|
$options = new \Couchbase\ClusterOptions();
|
$options->credentials( $user, $password );
|
|
// Connect to Couchbase Server
|
$cluster = new \Couchbase\Cluster("couchbase://{$host}", $options);
|
|
// Open bucket
|
$bucket = $cluster->bucket($bucketName);
|
$collection = $bucket->defaultCollection();
|
|
// Store a document
|
$result = $collection->upsert('u:king_arthur', array(
|
"email" => "kingarthur@couchbase.com",
|
"interests" => array("African Swallows")
|
));
|
|
// Retrieve a document
|
$result = $collection->get("u:king_arthur");
|
$doc = $result->content();
|
|
// Replace a document
|
$doc['new'] = 'PHP 7';
|
$options = new \Couchbase\ReplaceOptions();
|
$options->cas($result->cas());
|
$collection->replace("u:king_arthur", $doc, $options);
|
|
$collection->lookupIn('u:king_arthur', [ new \Couchbase\LookupGetSpec('interests[0]') ]);
|
$collection->mutateIn('u:king_arthur', [ new \Couchbase\MutateUpsertSpec('interests', 'European Swallows') ]);
|
|
Command I ran:
/usr/local/php/7.3dev/bin/php -n -d "extension=/usr/local/php/7.3dev/lib/php/extensions/debug-non-zts-20180731/couchbase.so" -d "output_handler=" -d "open_basedir=" -d "disable_functions=" -d "output_buffering=Off" -d "error_reporting=32767" -d "display_errors=1" -d "display_startup_errors=1" -d "log_errors=0" -d "html_errors=0" -d "track_errors=0" -d "report_memleaks=1" -d "report_zend_debug=0" -d "docref_root=" -d "docref_ext=.html" -d "error_prepend_string=" -d "error_append_string=" -d "auto_prepend_file=" -d "auto_append_file=" -d "ignore_repeated_errors=0" -d "precision=14" -d "memory_limit=128M" -d "log_errors_max_len=0" -d "opcache.fast_shutdown=0" -d "opcache.file_update_protection=0" -d "zend.assertions=1" -d "session.auto_start=0" -d "zlib.output_compression=Off" -d "mbstring.func_overload=0" -d "couchbase.log_level=FATAL" -f "/home/derick/dev/11-instana/instana-php-extensions/tests/instana_couchbase_003.php"
|
Result:
[Thu Jun 17 09:21:21 2021] Script: '/home/derick/dev/11-instana/instana-php-extensions/tests/instana_couchbase_003.php'
|
/home/derick/dev/php/php-src.git/Zend/zend_string.h(133) : Freeing 0x00007f01f08812d0 (48 bytes), script=/home/derick/dev/11-instana/instana-php-extensions/tests/instana_couchbase_003.php
|
=== Total 1 memory leaks detected ===
|
Checking it with GDB, I find that the "African Swallows" is the leaked string, as used in the upsert:
Breakpoint 1, php_message_handler_for_zend (message=4, data=0x7fffffffb950) at /home/derick/dev/php/php-src.git/main/main.c:1673
|
warning: Source file is more recent than executable.
|
1673 snprintf(memory_leak_buf, 512, "%s(%" PRIu32 ") : Freeing " ZEND_ADDR_FMT " (%zu bytes), script=%s\n", t->filename, t->lineno, (size_t)t->addr, t->size, SAFE_FILENAME(SG(request_info).path_translated));
|
(gdb) p *t
|
$1 = {addr = 0x7ffff44dd4b0, size = 48, filename = 0x5555565801d8 "/home/derick/dev/php/php-src.git/Zend/zend_string.h", orig_filename = 0x0, lineno = 133, orig_lineno = 0}
|
(gdb) p (zend_string*) t.addr
|
$2 = (zend_string *) 0x7ffff44dd4b0
|
(gdb) p (char*)((zend_string*) t.addr).val)
|
Junk after end of expression.
|
(gdb) p (char*)(((zend_string*) t.addr).val)
|
$3 = 0x7ffff44dd4c8 "African Swallows"
|