Solved

PHP Fatal error, out of memory

Posted on 2011-09-26
7
370 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 108

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

Zoho SalesIQ

Hassle-free live chat software re-imagined for business growth. 2 users, always free.

Question has a verified solution.

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

Foreword In the years since this article was written, numerous hacking attacks have targeted password-protected web sites.  The storage of client passwords has become a subject of much discussion, some of it useful and some of it misguided.  Of cou…
As a database administrator, you may need to audit your table(s) to determine whether the data types are optimal for your real-world data needs.  This Article is intended to be a resource for such a task. Preface The other day, I was involved …
The viewer will learn how to count occurrences of each item in an array.
The viewer will learn how to create and use a small PHP class to apply a watermark to an image. This video shows the viewer the setup for the PHP watermark as well as important coding language. Continue to Part 2 to learn the core code used in creat…

920 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

Need Help in Real-Time?

Connect with top rated Experts

16 Experts available now in Live!

Get 1:1 Help Now