php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #60644 Memory leak when retrieving non-empty arrays
Submitted: 2012-01-03 16:48 UTC Modified: 2014-10-10 20:15 UTC
Votes:3
Avg. Score:4.3 ± 0.5
Reproduced:2 of 2 (100.0%)
Same Version:1 (50.0%)
Same OS:2 (100.0%)
From: clarkwise at gmail dot com Assigned: ericsten (profile)
Status: Not a bug Package: WinCache (PECL)
PHP Version: 5.3.8 OS: Windows XP SP3, 32-bit
Private report: No CVE-ID: None
 [2012-01-03 16:48 UTC] clarkwise at gmail dot com
Description:
------------
There appears to be a memory leak when retrieving non-empty arrays from user cache. In the provided test script, the same amount of memory should be used by the script no matter how many times the loop is iterated. That is the case when storing empty arrays, numbers, strings, and objects, but the amount of memory consumed scales in proportion to the number of iterations when a non-empty array is stored in 'foo'.

# iterations 	array() 	array(0) 	'a string' 	42.9 	        new stdClass()
    10,000 	0.305710 MB 	 0.611053 MB 	0.305527 MB 	0.305504 MB 	0.309845 MB
   100,000 	0.305710 MB 	 3.357635 MB 	0.305527 MB 	0.305504 MB 	0.309845 MB
 1,000,000 	0.305710 MB 	30.823456 MB   	0.305527 MB 	0.305504 MB 	0.309845 MB
10,000,000   	0.305710 MB   	fatal error 	0.305527 MB   	0.305504 MB   	0.309845 MB  

(At 10,000,000 iterations, I get a fatal error because it hits my 128M memory limit at some point.)

I am using the latest stable Wincache version (1.1.0630.0), but it also occurs with the latest dev build I am able to try (1.2.614).

Test script:
---------------
wincache_ucache_set('foo', array(0));
for ($i = 0; $i < 1000000; ++$i) {
   $foo = wincache_ucache_get('foo');
}
printf('Mem used: %f MB<br />', memory_get_peak_usage()/1024/1024);

Expected result:
----------------
Something of similar magnitude to:

"Mem used: 0.306000 MB"

Actual result:
--------------
"Mem used: 30.823456 MB"

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2014-02-20 16:30 UTC] ericsten@php.net
-Assigned To: +Assigned To: ericsten
 [2014-06-27 22:54 UTC] ovidiu at softped dot com
I am also experiencing the same issue. 

IIS, PHP 5.3.28, Wincache 1.3.4 - memory leak
CLI, PHP 5.3.28, Wincache 1.3.4 - no memory leak
IIS, PHP 5.5.13, Wincache 1.3.5 - memory leak
CLI, PHP 5.5.13, Wincache 1.3.5 - memory leak
 [2014-06-28 17:20 UTC] ovidiu at softped dot com
Actually it happens with CLI PHP 5.3.28 as well. I had enablecli=off.
 [2014-06-30 12:42 UTC] ovidiu at softped dot com
Module Information 

Image Name: D:\Php\5.5.14\php5.dll   Symbol Type:  Export 
Base address: 0x00905a4d   Time Stamp:  Wed Jun 25 23:01:39 2014  
Checksum: 0x00000000   Comments:   
COM DLL: False   Company Name:  The PHP Group 
ISAPIExtension: False   File Description:  PHP Script Interpreter 
ISAPIFilter: False   File Version:  5.5.14 
Managed DLL: False   Internal Name:  PHP Script Interpreter 
VB DLL: False   Legal Copyright:  Copyright © 1997-2013 The PHP Group 
Loaded Image Name:  php5.dll   Legal Trademarks:  PHP 
Mapped Image Name:     Original filename:  php5.dll 
Module name:  php5   Private Build:   
Single Threaded:  False   Product Name:  PHP 
Module Size:  6.26 MBytes   Product Version:  5.5.14 
Symbol File Name:  php5.dll   Special Build:  & 

 
Function details

Function   php5!zend_hash_index_exists+43 
Source Line    
Allocation type   Heap allocation(s) 
Heap handle   0xa713c99d 
Allocation Count   8 allocation(s) 
Allocation Size   2 MBytes 
Leak Probability   80% 


Call stack sample 1

Address   0x00040000 
Allocation Time   00:00:10 since tracking started 
Allocation Size   256 KBytes 

Function Destination

php5!zend_hash_index_exists+43   ntdll!RtlAllocateHeap 
php5!emalloc+588    
php_wincache!alloc_oemalloc+a   php5!emalloc 
php_wincache!copyout_zval+15a    
php_wincache!copyout_bucket+156   php_wincache!copyout_zval 
php_wincache!copyout_hashtable+16d   php_wincache!copyout_bucket 
php_wincache!copyout_zval+202   php_wincache!copyout_hashtable 
php_wincache!zvcache_get+a9   php_wincache!copyout_zval 
php_wincache!zif_wincache_ucache_get+c8   php_wincache!zvcache_get 
php5!execute_ex+b26    
php5!zend_execute+14b   php5!execute_ex 
php5!zend_execute_scripts+de   php5!zend_execute 
php5!php_execute_script+14c   php5!zend_execute_scripts 
php!sapi_cli_single_write+f99   php5!php_execute_script 
php5!zend_save_error_handling+700    
php5!php_printf    
php5!zend_make_printable_zval+100    
php5!php_execute_simple_script+f0    
php5!php_log_err+100    
php5!zend_get_configuration_directive+10    
php5!php_remove_tick_function+20    
php5!config_zval_dtor+1e0    
php5!php_stream_read+350    
php5!zend_stack_is_empty+40    
php5!config_zval_dtor+180    
ntdll!_except_handler4    
php!sapi_cli_single_write+9079    
kernel32!BaseThreadInitThunk+e    
ntdll!__RtlUserThreadStart+20    
ntdll!_except_handler4    
ntdll!FinalExceptionHandlerPad17    
php!sapi_cli_single_write+8c56
 [2014-07-01 16:35 UTC] ericsten@php.net
Definitely leaking for arrays.  It looks like we're leaking a zval, a HashTable, and any nested zval's or HashTables of the Array that exists in the user cache, on every call to wincache_ucache_get().
For integral types, the return_value does not flow through the array copying path, and does not leak.
Under investigation for how to fix this.
 [2014-07-02 19:35 UTC] ericsten@php.net
The array objects (zval & HashTable objects) are allocated with emalloc, so the "leaked" items are allocated out of per-request memory.  This means that the memory will be free'd when the request/script completes.  I believe this reflects the intended use of the wincache_ucache_get function: it should be used only a few times within the lifetime of a single HTTP request/script execution.
Since the backing for the values in the array item returned from wincache_ucache_get is in memory controlled by Wincache, we hand-create the HashTable such that it doesn't have a destructor, and therefore doesn't deref the contained zval's (or free the items pointed at by the zval's zvalue_value).  Hence, Wincache depends upon the callers only calling wincache_ucache_get infrequently during a single script.
 [2014-10-10 20:15 UTC] ericsten@php.net
-Status: Assigned +Status: Not a bug
 [2014-10-10 20:15 UTC] ericsten@php.net
[Mopping up old bugs]

Resolving this as "By Design", since this WinCache is doing exactly what it's supposed to do.

Thx!
    --E.
 
PHP Copyright © 2001-2019 The PHP Group
All rights reserved.
Last updated: Tue Nov 19 20:01:37 2019 UTC