Allowed memory size of # bytes exhausted

I've encountered the dreaded error-message, possibly through-painstaking effort, PHP has run out of memory:

Allowed memory size of #### bytes exhausted (tried to allocate #### bytes) in file.php on line 123

Increasing the limit

If you know what you're doing and want to increase the limit see memory_limit:

ini_set('memory_limit', '16M');
ini_set('memory_limit', -1); // no limit

Beware! You may only be solving the symptom and not the problem!

Diagnosing the leak:

The error message points to a line withing a loop that I believe to be leaking, or needlessly-accumulating, memory. I've printed memory_get_usage() statements at the end of each iteration and can see the number slowly grow until it reaches the limit:

foreach ($users as $user) {
    $task = new Task;
    $task->run($user);
    unset($task); // Free the variable in an attempt to recover memory
    print memory_get_usage(true); // increases over time
}

For the purposes of this question let's assume the worst spaghetti code imaginable is hiding in global-scope somewhere in $user or Task .

What tools, PHP tricks, or debugging voodoo can help me find and fix the problem?


PHP doesn't have a garbage collector. It uses reference counting to manage memory. Thus, the most common source of memory leaks are cyclic references and global variables. If you use a framework, you'll have a lot of code to trawl through to find it, I'm afraid. The simplest instrument is to selectively place calls to memory_get_usage and narrow it down to where the code leaks. You can also use xdebug to create a trace of the code. Run the code with execution traces and show_mem_delta .


There are several possible points of memory leaking in php:

  • php itself
  • php extension
  • php library you use
  • your php code
  • It is quite hard to find and fix the first 3 without deep reverse engineering or php source code knowledge. For the last one you can use binary search for memory leaking code with memory_get_usage


    Here's a trick we've used to identify which scripts are using the most memory on our server.

    Save the following snippet in a file at, eg, /usr/local/lib/php/strangecode_log_memory_usage.inc.php :

    <?php
    function strangecode_log_memory_usage()
    {
        $site = '' == getenv('SERVER_NAME') ? getenv('SCRIPT_FILENAME') : getenv('SERVER_NAME');
        $url = $_SERVER['PHP_SELF'];
        $current = memory_get_usage();
        $peak = memory_get_peak_usage();
        error_log("$site current: $current peak: $peak $urln", 3, '/var/log/httpd/php_memory_log');
    }
    register_shutdown_function('strangecode_log_memory_usage');
    

    Employ it by adding the following to httpd.conf:

    php_admin_value auto_prepend_file /usr/local/lib/php/strangecode_log_memory_usage.inc.php
    

    Then analyze the log file at /var/log/httpd/php_memory_log

    You might need to touch /var/log/httpd/php_memory_log && chmod 666 /var/log/httpd/php_memory_log before your web user can write to the log file.

    链接地址: http://www.djcxy.com/p/19920.html

    上一篇: 内存泄漏(有点)与静态std :: vector

    下一篇: 允许的#字节内存大小已耗尽