Forum Moderators: coopster

Message Too Old, No Replies

Fatal Error (memory size). but I'm not sure where it lies?

Fatal error: Allowed memory size of 33554432 bytes exhausted

         

jayayseekay

11:12 am on Mar 31, 2009 (gmt 0)

10+ Year Member



Hi,

I'm new here and would appreciate any assistance! I've run into a fatal error on my web project and I'm not quite sure if the error lies in my (probably extremely poor) coding or in the PHP configuration.

I am currently making a script to allow users to upload images into a directory, and then list the directory contents so they can use the information to see what images are hosted (so they can then use the images in an article).

The script for uploading pictures seems to be working fine (with smaller files), as does the directory listing part. However, I was thinking "well, someone may want to upload a photo, and you know what photos are like these days with these 3,412.6 megapixel camerawotsits and so on, so I thought I'd up the max file size that can be uploaded to ~3mb.

Testing this with a nice 2.5mb file, I very quickly ran into the following error:

Fatal error: Allowed memory size of 33554432 bytes exhausted (tried to allocate 12288 bytes) in /public_html/uploader.php on line 64

I looked at around line 64, and it turns out that where I'd taken the photo uploading script from another area of my site, I'd left in a couple if/then statements setting new variables. Being redundant checks and variables, I removed these, cursed my silly self for the 100th time today, and tried again, this time with success. I then upped the file size limit to ~5mb and it now uploads 5mb pics without error.

Which means the problem is fixed, right? Except it's bugging me still. All those lines did were set a few variables that would end up not being used... if they can cause that error, who knows what other lax bit of coding I've done that's going to bring the site to its knees?

I've looked into the problem and all advice seems to point towards the memory_limit of the php.ini configuration - I use a hosting company however that doesn't allow me access to the php.ini (I'm not exactly too ambitious in my plans right now!) so I can't adjust this. Some of my research has suggested the error can be down to bad code leaks etc? I'm running a very very small mysql DB with my site so there's not a crazy amount for the site to do except for this particular bit where I upload images to it!

Here's the area of code around line 64. Line 64 in particular is the one marked with ***s, and I've highlighted (with // comments) the redundant code that once removed fixed the problem (obviously the *s are not there in the code I used on the site):

$sent = $_POST["sent"];

if ($sent == "yes") {
if ((($_FILES["file"]["type"] == "image/gif")
¦¦ ($_FILES["file"]["type"] == "image/jpeg")
¦¦ ($_FILES["file"]["type"] == "image/pjpeg")
¦¦ ($_FILES["file"]["type"] == "image/png"))
&& ($_FILES["file"]["size"] < 3146000))
{
if ($_FILES["file"]["error"] > 0)
{
echo "Return Code: " . $_FILES["file"]["error"] . "<br />";
}
else
{
// redundant code start!

$uploadedfile = $_FILES['file']['tmp_name'];

if ($_FILES["file"]["type"] == "image/gif") { $extension = ".gif"; $src = imagecreatefromgif($uploadedfile); }
*** if ($_FILES["file"]["type"] == "image/jpeg") { $extension = ".jpg"; $src = imagecreatefromjpeg($uploadedfile); }
if ($_FILES["file"]["type"] == "image/pjpeg") { $extension = ".jpg"; $src = imagecreatefromjpeg($uploadedfile); }
if ($_FILES["file"]["type"] == "image/png") { $extension = ".png"; $src = imagecreatefrompng($uploadedfile); }

// redundant code end!

$directory1 = "uploads/" . "$usn" . "/";
if (!file_exists($directory1)) { mkdir($directory1, 0777); }

move_uploaded_file($_FILES["file"]["tmp_name"], $directory1 . $_FILES["file"]["name"]);

Thanks for any and all help and suggestions, I'll happily post more of my code if requested to fix this!

coopster

3:46 pm on Mar 31, 2009 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



Welcome to WebmasterWorld, jayayseekay.

It is the creation of your image from jpeg that is giving you fits, I'm certain. Although the file size in and of itself may only be a certain size, the function requires more memory than just the size of the file itself.

Some helpful (required) reading from past threads regarding similar issues:

More PHP image upload problems [webmasterworld.com]
Uploading big images turn to black! [webmasterworld.com]
Memory usage when rotating photos in PHP [webmasterworld.com]

penders

4:17 pm on Mar 31, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



jpeg is a compressed image format. When you call imagecreatefromjpeg() the jpeg image is uncompressed and stored in memory (+ an additional PHP overhead) and this can easily get massive. A 10mp 24bit image might squash down to 3MB as a jpeg, but uncompressed that is 30MB minimum (and probably quite a bit more with PHP's overhead - reqd in order to manipulate that image).

Presumably you want to call imagecreatefromjpeg() in order to create a smaller web-displayable image?

rocknbil

8:27 pm on Mar 31, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



^ ^ ^ That is precisely it, and also why the default upload limitation is 2MB. When you get larger than that, the GD library just.won't.do.

I just finished a project for the exact same reasons you stated - the client wanted to allow up to 10MB file uploads to be resized to "reasonable" sizes for final storage because his users don't understand images and would load them directly from their cameras. When resized, the humongous files are overwritten with the resized version and a thumb is created.

You can try fiddling with the .htaccess per-directory to allow PHP to slurp up more memory and increase the timeout, and it will work - the problem with that is it then becomes a laborious task on your server, eating up memory with every upload. On a busy site, it may cause a crash.

The solution lies in Imagick. PHP's Imagick uses ImageMagick to process images, which has two advantages:

- The image manipulation is an external process, so it doesn't require that PHP takes up more memory.
- ImageMagick does it's own memory management, so if it's using more memory than allocated is does so on virtual disk (unverified, the exact methods may differ from my obtuse description, but the bottom line is ImageMagick doesn't hog your system memory.)

You may still have to up the timeout setting via .htaccess for large files, but this works very very well when you step outside PHP defaults. Additionally, ImageMagick has *TONS* more options you can't do with GD that involve image compositing, truetype manupulation, filters, and even manages non-web file formats, such as uploaded CMYK images.

But it can be a bear to get it installed right. :-( You need to a) install ImageMagick binaries, then b) Install the appropriate extensions for Imagick, none of which I understand; I had my admin do it for me. He hates me now. :-)

Torrid Story of Huge Files Using GD [webmasterworld.com]

Sample of difficulties with Imagick [webmasterworld.com] Learn from my mistakes and consider the obvious FIRST! :-)

jayayseekay

9:41 am on Apr 2, 2009 (gmt 0)

10+ Year Member



Thank you for the past references coopster, I'm looking into them now! Yes that sounds right.

Well penders, the code was left in there by mistake so actually wasn't doing anything (well obviously it was, but it wasn't *meant to be*) - but yeah, I think the way things are going I'm going to have to use the function in this form to create a 'thumbnail' version at some point - so looks like I'm limiting the file size back down again!

And thanks for the Imagick tip rocknbil, I'll definitely keep it in mind but right now I think it's a step beyond me and I'm not sure just how technical my hosts are so I'm not gonna trust them with it just yet either!

Thanks for all your help everyone!

rocknbil

4:12 pm on Apr 2, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Well, installation of ImageMagick and Imagick should be your host's ball - they may already have it. Pull a phpinfo on your site, it will be obvious if it is. The usage is every bit as easy as the GD toolkit and the documentation on php.net will give you all the info you need.

If you're getting fatal memory errors, unless you're on a dedi/VPS, this could produce some serious problems for you if you keep upping the memory limit per .htaccess - your host may pull your plug. :-)