php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #42356 memory allocation error using GD
Submitted: 2007-08-21 01:28 UTC Modified: 2007-08-22 05:36 UTC
From: myteamz at rogers dot com Assigned: pajoye (profile)
Status: Not a bug Package: Reproducible crash
PHP Version: 5.2.3 OS: Windows XP SP2
Private report: No CVE-ID: None
View Add Comment Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
You can add a comment by following this link or if you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: myteamz at rogers dot com
New email:
PHP Version: OS:

 

 [2007-08-21 01:28 UTC] myteamz at rogers dot com
Description:
------------
I am creating a script to produce a PNG image of a chart showing common ancestors of several individuals, using the gd functionality supplied with php.  After processing the input, including many calls to MySQL (version 5.0.2) all running on Apache 2.2 on Windows XP SP2, I am trying to allocate the image resource.  This works for very small trees, but fails on all calls with large trees.

The PHP error message is:
Fatal error: Allowed memory size of 33554432 bytes exhausted (tried to allocate 13770 bytes) in C:\Program Files\Apache Software Foundation\Apache2.2\htdocs\GenChart\drawgraph.php on line 116

The offending code is:
$im = imagecreate ($xsize, $ysize);

Reproduce code:
---------------
Lots of memory allocation/freeing is occurring in the script prior to this call.  I have included several debug lines prior to the offending call, as below:

$memMax = ini_get("memory_limit");
$memUsed = memory_get_usage(true);
$xMax = round(30000000-intval($memUsed/$ysize),-3);
$xsize = min($xMax,max($xsize,4000));
dumpData("have used $memUsed of $memMax memory");
dumpData("trying to create image of size ($xsize,$ysize)");
$im = imagecreate ($xsize, $ysize);

The output, on crash, is

have used 6815744 of 32M memory
trying to create image of size (13770,990)

Expected result:
----------------
I have changed the script to produce standard HTML output for debugging purposes, which allows me to get this info.  When running as intended, with a small tree/image, the script should and does run successfully, creating an image, and returning it as a .PNG image.  Running the same debug code for a small image (with no crash), the output is:

have used 6553600 of 32M memory
trying to create image of size (4000,690)



Actual result:
--------------
When running in debug mode for a large tree/image, the debug output is:

have used 6815744 of 32M memory
trying to create image of size (13770,990)

When running as intended, the script fails and no image is returned to the browser.

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2007-08-21 05:48 UTC] pajoye@php.net
"Fatal error: Allowed memory size of 33554432 bytes exhausted (tried to
allocate 13770 bytes) in C:\Program Files\Apache Software"

I'm sorry but it has nothing to do with GD. imagecreate tries to allocate the memory it needs for an image but your application seems to have already used most of the available limit (32M in this case).

By the way, fatal errors are not crashes or do you have a real crash? (segfault). If yes post a comment I will reopen this bug and move it to the engine category.
 [2007-08-21 14:21 UTC] myteamz at rogers dot com
You have ignored the other submitted info that shows (via call to memory_get_usage(true)) that the memory in use is actually less than 7M.

Either the function call is reporting incorrect values, or there is a problem in the memory manager believing 32M is in use.

I have subsequently added a call to memory_get_peak_usage(true), and it reports the same value as memory_get_usage(true), indicating I have come nowhere near using 32M.
 [2007-08-21 14:31 UTC] derick@php.net
Your image takes 13770*990*4 bytes, which is ca. 54mb. That doesn't fit in 32 mb memory limit.
 [2007-08-21 15:25 UTC] myteamz at rogers dot com
With understanding of how much memory GD uses per pixel (4 bytes), I am able to scale image request size to fit in memory, but result is that image is not large enough to build tree.

When increasing memory_limit to 128M, I still run into 32M limit, and upon looking further, it appears that default Apache Windows distro is built with MAX_PROCESS_SIZE = 32M.

This implies that the default max image GD can handle (for height of 1024) is about 32M/1024/4 = 8K.

When looking further into GD documentation, there is a reason why I am using imagecreate instead of imagecreatetruecolor.  The GD docs say gdImageCreate(sx, sy) has a 256 color limit, or 1 byte per pixel, while gdImageCreateTrueColor(sx, sy) has "an essentially unlimited number of colors" - presumably 32 bit or 4 bytes per pixel.

When I change my call to use imagecreatetruecolor instead of imagecreate, the memory usage is exactly the same, suggesting the PHP imagecreate is calling the GD gdImageCreateTrueColor and reducing the available image size by a factor of 4.  If this is the case, why?
 [2007-08-21 17:44 UTC] pajoye@php.net
"When I change my call to use imagecreatetruecolor instead of
imagecreate, the memory usage is exactly the same, suggesting the PHP
imagecreate is calling the GD gdImageCreateTrueColor and reducing the
available image size by a factor of 4.  If this is the case, why?"

That's not the case. You consider the values returned by the memory info functions are accurate, they are not.

"This implies that the default max image GD can handle (for height of
1024) is about 32M/1024/4 = 8K."

Completely wrong, you are looking at the wrong place to fix your problem. If you have doubt about the cause (memory limit), try to run your script (and only what you show here) using CLI (command line).

 [2007-08-21 19:39 UTC] myteamz at rogers dot com
On looking further, both imagecreate andimagecreatetruecolor were working, and use different amounts of memory.  However, the amounts are different than 4 bytes in both cases.

For imagecreate, 2 bytes (+marginal overhead) are allocated.
For imagecreatetruecolor, 5 bytes (+about .15 per pixel) are allocated.

These were calculated using the following script;

<?php
    for ($i=0;$i<2;$i++) {
        println("iteration = $i");
        $mUsed = memory_get_usage(true);
        $mPeak = memory_get_peak_usage(true);
        println(" $mUsed, $mPeak");
        
        $xSize=8192;
        $ySize=1024;
        if ($i==0) $im = imagecreate($xSize,$ySize);
        else $im = imagecreatetruecolor($xSize,$ySize);
        
        $mUsed2 = memory_get_usage(true);
        $mPeak2 = memory_get_peak_usage(true);
        println(" $mUsed2, $mPeak2");
        $iUsed = $mUsed2-$mUsed;
        $perPixel = $iUsed/($xSize*$ySize);
        println(" incremental memory - $iUsed ($perPixel per pixel)");
        
        imagedestroy($im);
        
        $mUsed3 = memory_get_usage(true);
        $mPeak3 = memory_get_peak_usage(true);
        println(" $mUsed3, $mPeak3");
        println;
    }
    
function println($text) {print("$text\n<BR>");}
?>

From this, it appears there is 1 or 4 bytes for color, plus 1 byte for something else.  This should be in the docs.

Consider the item closed.
 [2007-08-22 05:36 UTC] pajoye@php.net
"From this, it appears there is 1 or 4 bytes for color, plus 1 byte for
something else.  This should be in the docs"

I know exactly how much memory a GD image uses. I can't say (well I can but not easily) how much memory is used by a PHP resource, its variable, the code used to initialize it.

Not a bug > bogus remains.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Apr 25 02:01:30 2024 UTC