• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 404
  • Last Modified:

PHP Fatal error, out of memory

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
pda4me
Asked:
pda4me
1 Solution
 
neorushCommented:
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
 
pda4meAuthor Commented:
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
 
neorushCommented:
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
Cloud Class® Course: Microsoft Office 2010

This course will introduce you to the interfaces and features of Microsoft Office 2010 Word, Excel, PowerPoint, Outlook, and Access. You will learn about the features that are shared between all products in the Office suite, as well as the new features that are product specific.

 
neorushCommented:
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
 
boon86Commented:
you might increase it to higher value such as:

memory_limit = 512M

since you have 8GB RAM
0
 
Ray PaseurCommented:
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
 
pda4meAuthor Commented:
Thanks!
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Cloud Class® Course: Microsoft Exchange Server

The MCTS: Microsoft Exchange Server 2010 certification validates your skills in supporting the maintenance and administration of the Exchange servers in an enterprise environment. Learn everything you need to know with this course.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now