note 88911 deleted from function.fread by danbrown
| From: | danbrown@php.net | Date: | Sat, 28 Feb 2009 18:44:38 +0000 |
| Subject: | note 88911 deleted from function.fread by danbrown | ||
| References: | 1 | Groups: | php.notes |
| Request: | Send a blank email to php-notes+get-151261@lists.php.net to get a copy of this message | ||
Note Submitter: shaunspiller at dontspammegmail dot com
----
fread has a bug than can cause large memory leaks if you're storing separate strings from
multiple reads, or even just a single string if the length parameter is large.
The strings returned always allocate *length* bytes (the parameter in the call), even if the total
amount of returned data is tiny.
E.g.,:
<?php
file_put_contents('temp.txt', 'a few bytes');
$fp = fopen('temp.txt', 'rb');
echo 'Memory usage: ' . number_format(memory_get_usage(), null, null, ' ') .
"\n";
$x = fread($fp, 1024 * 1024);
fclose($fp);
echo 'Memory usage: ' . number_format(memory_get_usage(), null, null, ' ') .
"\n";
echo 'String length: ' . strlen($x);
?>
Example output:
Memory usage: 67 520
Memory usage: 1 117 056
String length: 11
After just one fread call, the string $x now takes over 1 MB of memory for 11 bytes of data, and
will stay that way until you unset or release it. This affects network streams too.
The bug was apparently dismissed as "won't fix" (or "wont fix" actually):
http://bugs.php.net/bug.php?id=34471
If you want to avoid it, re-alloc the string before storing it, and the wasted memory will
disappear. Specifying a smaller length value avoids creating the large buffer in the first place
too.
E.g.:
<?php
$x = substr(fread($fp, 65536), 0);
?>