[2 days left] What’s wrong with your cloud strategy? Learn why multicloud solutions matter with Nimble Storage.Register Now

x
?
Solved

PHP Fatal error, out of memory

Posted on 2011-09-26
7
Medium Priority
?
392 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
7 Comments
 
LVL 6

Accepted Solution

by:
neorush earned 2000 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
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
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 111

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

On Demand Webinar - Networking for the Cloud Era

This webinar discusses:
-Common barriers companies experience when moving to the cloud
-How SD-WAN changes the way we look at networks
-Best practices customers should employ moving forward with cloud migration
-What happens behind the scenes of SteelConnect’s one-click button

Question has a verified solution.

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

In this series, we will discuss common questions received as a database Solutions Engineer at Percona. In this role, we speak with a wide array of MySQL and MongoDB users responsible for both extremely large and complex environments to smaller singl…
Originally, this post was published on Monitis Blog, you can check it here . In business circles, we sometimes hear that today is the “age of the customer.” And so it is. Thanks to the enormous advances over the past few years in consumer techno…
The viewer will learn how to dynamically set the form action using jQuery.
The viewer will learn how to look for a specific file type in a local or remote server directory using PHP.
Suggested Courses

656 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