php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #46181 memory leak on garbage collecting function return values
Submitted: 2008-09-26 10:28 UTC Modified: 2008-09-26 21:19 UTC
From: xl269 at cam dot ac dot uk Assigned:
Status: Not a bug Package: Performance problem
PHP Version: 5.3CVS-2008-09-26 (CVS) OS: debian gnu/linux lenny
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: xl269 at cam dot ac dot uk
New email:
PHP Version: OS:

 

 [2008-09-26 10:28 UTC] xl269 at cam dot ac dot uk
Description:
------------
I have no idea if my explanation of this bug is correct, but here's a guess anyway.

PHP does not seem to garbage collect return values from functions, when they are operated-assigned (eg. $v = func() + 5; or $v = func()." ";) to a variable in the caller. but this is fine for direct assignments (eg. $v = func();)

It would seem from this that PHP is storing functions' return values internally as if they were pointed to by a variable (that doesn't exist in the script), and using copy-on-write to avoid copying this data when it's assigned to an actual script variable. However copy-on-write, doesn't trigger when there is an operation on this data before this assignment.


Reproduce code:
---------------
<?php

define('LF', chr(10));

// define('REALLY_LONG_STRING', str_repeat("really ", 65536)."long string");

function generic($for, $title) {
	mem('g+');
	$data = '<abbr title="information for '.$for.'">'.$title.'</abbr>';
	// $data = '<abbr title="information for '.$for.'">'.$title.'</abbr>'.REALLY_LONG_STRING;
	mem('g-');
	return $data;
}

function lol1() {
	mem('l1+');
	$data = " ".generic("name", "test")." ";
	mem('l1-');
	return $data;
}

function lol2() {
	mem('l2+');
	$data = generic("name", "test");
	mem('l2-');
	return $data;
}

echo memory_get_usage().LF;
for ($i=0; $i<8; $i++) {
	$a[] = lol2();
	echo memory_get_usage().LF;
	$a[] = lol1();
	echo memory_get_usage().LF;
}

?>


Expected result:
----------------
see below

Actual result:
--------------
635168
635240 l2+
635496 g+
635672 g-
635672 l2- (no memory leak here)
635928
636024 l1+
636072 g+
636184 g-
636248 l1- (this value should only be 2 bytes larger than the previous)
636336


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2008-09-26 10:34 UTC] xl269 at cam dot ac dot uk
oh, i forgot to add, if you uncomment those lines in the code provided, the bug doesn't appear. which odd, since it appears for the smaller data.
 [2008-09-26 19:54 UTC] johannes@php.net
"Fatal error: Call to undefined function mem() " therefore I couldn't do a check, but I assume it'S the same as bug #46180
 [2008-09-26 21:19 UTC] xl269 at cam dot ac dot uk
sorry, mem() just prints out the memory:

function mem($k) { echo memory_get_usage().' '.$k.LF; }

still, if this is an effect of php's caching system as you state in the other bug report, it's not doing its job. i'm running a cli daemon and this bug is the main cause of leaks - around 2MB per day, and that's based on lightest possible use (ie, doing pretty much nothing).

and there's hardly any documentation available on this subject.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sun Dec 22 11:01:30 2024 UTC