How to recover from a fatal error “Allowed memory size exhausted”

前端 未结 7 882
梦如初夏
梦如初夏 2021-01-04 08:52

Do you know any solution to recover from the PHP fatal error : \"Allowed memory size ... exhausted\"

I have a shutdown function that is called when a fatal

相关标签:
7条回答
  • 2021-01-04 09:08

    Got an idea for an untested trick and I'd be happy to know if it helped. Allocate some global variable when you first register the shutdown function and release it when the shutdown function's code is first executed. You may then have sufficient memory to create the Exception object. Let me know if it worked and please publish the code here.

    0 讨论(0)
  • 2021-01-04 09:11

    The regular way to customize error handling is through

    set_error_handler — Sets a user-defined error handler function

    The docs for this function state (emphasis mine):

    The following error types cannot be handled with a user defined function: E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR, E_COMPILE_WARNING, and most of E_STRICT raised in the file where set_error_handler() is called.

    So, it won't work regularly, but you can try

    • the approach given in the comments of PHP manual, using output buffering or
    • the approach using the register_shutdown_function

    As of PHP7, Errors and Exceptions are Throwables, so you can try/catch them:

    • http://php.net/manual/en/language.errors.php7.php
    0 讨论(0)
  • 2021-01-04 09:17

    This worked fine for me:

    try {
        ini_set('memory_limit', (ini_get('memory_limit')+1).'M');
    } catch(Exception $e) {}
    

    This assumes your memory limit is in the format 123M.

    0 讨论(0)
  • 2021-01-04 09:20

    This error is a fatal error - that means you cannot recover from it. If PHP has hit it's memory limit, it won't be able to allocate any more memory to create your exception and any other memory it needs to carry on its execution.

    There is another type of error - "catchable fatal error" which as the name suggests, can be caught in a try/catch, but unfortunately the memory size allocation is not one of them.

    0 讨论(0)
  • 2021-01-04 09:21
    if((memory_get_usage() / 1024 /1024) < 70)
    

    I simply divide the memory_get_usage by 1024 squared to compare it to a 'normal' megabyte value of '70'.

    I ran into memory problems with php inside a for loop and wrote this simple if statement to prevent my script from setting off a fatal error. In addition, the server I was operating on didn't allow me to modify the memory limit (this is often the case in some cloud offerings like openshift or large web hosts like dreamhost.) I didn't really notice any serious performance degradations (in php 5.3 which may handles functions such as this slightly differently than php 4.x or 5.x... at any rate the performance implication of a script giving a fatal error outweighs any overhead the function call may force. And would also prevent a runaway script from consuming all available ram.

    Many may argue; oh hey your software isn't optimized. Yes. You're probably right; but with complex data sets you can only squeeze so much performance out before you need to throw more memory at it; and hunting down memory errors in an ajax flow can be very frustrating; especially when you aren't sure where your log files are.

    0 讨论(0)
  • 2021-01-04 09:25

    One I can think of is that you when you're doing your memory intensive operation you manually query memory_get_usage() on a regular basis (e.g. every loop iteration) and dump out your headers/error when it goes over some failsafe value which is below the script limit. It will slow your script down a lot, but at least you'll get something back.

    Or, and you may not be able to do this, run the memory intensive stuff as a CLI-based script called from inside your web-based stuff by using exec. The CLI part might fall over, but the web part will be able to report on it.

    0 讨论(0)
提交回复
热议问题