php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #47103 memory leak using foreach and references
Submitted: 2009-01-14 16:35 UTC Modified: 2009-04-08 15:50 UTC
Votes:8
Avg. Score:3.9 ± 1.4
Reproduced:7 of 7 (100.0%)
Same Version:5 (71.4%)
Same OS:3 (42.9%)
From: soywiz at gmail dot com Assigned:
Status: Not a bug Package: Scripting Engine problem
PHP Version: 5.*CVS,6CVS (2009-01-15) OS: *
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: soywiz at gmail dot com
New email:
PHP Version: OS:

 

 [2009-01-14 16:35 UTC] soywiz at gmail dot com
Description:
------------
This snippet causes an out of memory. It seems that it's duplicating the value (it's trying to allocate a memory chunk as large as each element on the array) and it's not freeing it.

The problem persists even with a unset($v); within the foreach.

I reproduced it using php 5.2.8-cli on windows and php 5.2.5-cgi on linux.

I think it should work, but maybe it's a php feature?

Reproduce code:
---------------
<?php
	$a = array_fill(0, 99999, str_repeat('*', 9991));
	foreach ($a as &$v) ;
?>


Expected result:
----------------
Don't waste all the memory

Actual result:
--------------
Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 9992 bytes) in test.php on line 3

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2009-01-14 17:35 UTC] crrodriguez at opensuse dot org
looks like expected, do not use foreach value by reference, it is know to have "apparently unexpected behaviors" that are normal.
 [2009-01-15 14:51 UTC] jani@php.net
This is NOT expected but might not be fixable. And foreach with reference is supposed to work without leaks.
 [2009-01-15 14:52 UTC] jani@php.net
This worked: 
# php -dmemory_limit=1000M t.php 
int(1018887988)

That number is from memory_get_usage() after the foreach.. :)
 [2009-04-08 15:50 UTC] lbarnaud@php.net
This is not a bug.

> $a = array_fill(0, 99999, str_repeat('*', 9991));

This adds 99999 times the *same* string to the array. This string ends with a refcount of 99999, and the array occupies only the memory required for *one* string of 9991 bytes.

> foreach ($a as &$v) ;

At this point the engine must duplicate the string, place it at the current index, and return a reference to it (because if you assign to it, you do not want all values of the array to be changed at once).

When you unset $v, you remove a reference from it, and leave a copy in the array.

You get closely the same memory usage with the following script, which does the same thing:

$a = array();
for($i = 0; $i < 99999; ++$i) {
        $a[] =  str_repeat('*', 9991);
}
foreach ($a as &$v);

 
PHP Copyright © 2001-2025 The PHP Group
All rights reserved.
Last updated: Wed Jul 16 20:01:32 2025 UTC