Solved

PHP Fatal error, out of memory

Posted on 2011-09-26
7
376 Views
Last Modified: 2012-05-12
I am trying to run a PHP script that parses an XML file and inserts into a database in the same directory.  It runs find on my system but when I move it to the server, I get the following error.  How do I fix?

Fatal error: Out of memory (allocated 17563648) (tried to allocate 17043391 bytes) in /home/directory/lib55as.xml.php on line 122

Open in new window


on line 122 of this file, I have the following:

		// format source;
		if($typeof == NULL)
			$data = $src;
		elseif($typeof == 'FILE') {
			$fop  = @fopen($src, 'r');
			$data = "";
			if ($fop) {
				while(!feof($fop))
					$data .= fgets($fop, 4096);  // Line 22 here
						
			}
			@fclose($fop);
		}

Open in new window



Here is a copy of the entire function including line 122:

	/**
	 * parse
	 * Set the parser Xml and theses options.
	 * Xml file could be a string, a file, or curl.
	 * When the source is loaded, we run the parse.
	 * After, we clean all the memory and variables,
	 * and return the result in an array.
	 *
	 * @access  public
	 * @param   src       string    Source
	 * @param   typeof    string    Source type : NULL, FILE, CURL.
	 * @param   encoding  string    Encoding type.
	 * @return  array
	 */
	function parse ( $src, $typeof = 'FILE', $encoding = 'UTF-8' ) {

		// ini;
		// (re)set array;
		$this->pOut = array();
		$this->parser = xml_parser_create();

		xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
		xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, $encoding);

		xml_set_object($this->parser, $this);
		xml_set_element_handler($this->parser, 'startHandler', 'endHandler');
		xml_set_character_data_handler($this->parser, 'contentHandler');

		if(empty($src))
			trigger_error('Source could not be empty.', E_USER_ERROR);     

		// format source;
		if($typeof == NULL)
			$data = $src;
		elseif($typeof == 'FILE') {
			$fop  = @fopen($src, 'r');
			$data = "";
			if ($fop) {
				while(!feof($fop))
					$data .= fgets($fop, 4096);  // Line 122 here
						
			}
			@fclose($fop);
		}
		elseif($typeof == 'CURL') {
			$curl = curl_init();
			curl_setopt($curl, CURLOPT_URL, $src);
			curl_setopt($curl, CURLOPT_HEADER, 0);
			$data = curl_exec($curl);
			curl_close($curl);
		}
		else
			return trigger_error('Xml parser need data.', E_USER_ERROR);

		if ($data > "") {
			// parse $data;
			$parse = xml_parse($this->parser, $data);
			if(!$parse)
				return trigger_error('XML Error : %s at line %d.', E_USER_ERROR,
					array(xml_error_string(xml_get_error_code($this->parser)),
						xml_get_current_line_number($this->parser)));
	
			// destroy parser;
			xml_parser_free($this->parser);
	
			// unset extra vars;
			unset($data,
				  $this->track,
				  $this->tmpLevel);
	
			// remove global tag and return the result;
			return $this->pOut[0][key($this->pOut[0])];
		} else {
			return "";
		}
			
	}

Open in new window

0
Comment
Question by:pda4me
7 Comments
 
LVL 6

Accepted Solution

by:
neorush earned 500 total points
ID: 36657397
The problem is:
$data .= fgets($fop, 4096);
This loads the entire file into $data, if the file is bigger than the memory available to php you will get this error.  This function is written incorrectly for loading the whole file, it should just use file_get_contents() rather than read the file line by line as this would be faster.  But that would still result in an out of memory error since the entire file is saved to memory.

Instead you have to do something with every single line as it is read with fgets().  Which since this function is designed to return the entire XML file as an array, you would have to modify what ever script is calling this function as well.  Its a lot more complicated than just swapping a few lines since this is going to change the application quite a bit.

Two solutions, you have to go back and edit a lot more code than just this function, or you need more ram (memory) on your server.
0
 

Author Comment

by:pda4me
ID: 36660444
thanks neo, both local machine and remote have 8GB of RAM and it works fine on the one system...is it possible there is a setting in apache or php that is limiting the available memory?  Do you know what setting that would be?
0
 
LVL 6

Expert Comment

by:neorush
ID: 36662116
yes, there are limits per script set in php.ini
you can find a line like this in php.ini
memory_limit = 16M ;

you can also try adding a flag in a .htaccess file to change it:
php_value memory_limit 16M

or you can try changing it with php code:
<?php
ini_set('memory_limit', '16M');
?>

just change 16M to however many megabytes of memory you want available for the script.
0
PRTG Network Monitor: Intuitive Network Monitoring

Network Monitoring is essential to ensure that computer systems and network devices are running. Use PRTG to monitor LANs, servers, websites, applications and devices, bandwidth, virtual environments, remote systems, IoT, and many more. PRTG is easy to set up & use.

 
LVL 6

Expert Comment

by:neorush
ID: 36664475
I should also clarify the diffences in the above:
Changes memory for every page on the entire server:
memory_limit = 16M ;

Changesmemory  for every page in the current directory and any subdirectories:
php_value memory_limit 16M

Changes memory for the current script:
ini_set('memory_limit', '16M');

So naturally you'll want to work backwards with these.  e.g. see if you can just change it for the script, then see if you need to change it for the directory, and finally change it for the entire server.
0
 
LVL 7

Expert Comment

by:boon86
ID: 36712310
you might increase it to higher value such as:

memory_limit = 512M

since you have 8GB RAM
0
 
LVL 109

Expert Comment

by:Ray Paseur
ID: 36713874
You might want to post either the input data or a link to the input data.  At EE we have seen lots of code that does not work, but given the input data and a clear description of the desired outputs we are sometimes able to create code that does work.

The man page references about memory sizes are available here.
http://php.net/manual/en/ini.core.php
http://php.net/manual/en/function.memory-get-peak-usage.php
http://php.net/manual/en/function.memory-get-usage.php
0
 

Author Closing Comment

by:pda4me
ID: 36717813
Thanks!
0

Featured Post

Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Developers of all skill levels should learn to use current best practices when developing websites. However many developers, new and old, fall into the trap of using deprecated features because this is what so many tutorials and books tell them to u…
This article discusses how to create an extensible mechanism for linked drop downs.
Learn how to match and substitute tagged data using PHP regular expressions. Demonstrated on Windows 7, but also applies to other operating systems. Demonstrated technique applies to PHP (all versions) and Firefox, but very similar techniques will w…
This tutorial will teach you the core code needed to finalize the addition of a watermark to your image. The viewer will use a small PHP class to learn and create a watermark.

839 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question