usage unlimited reported recommended memory_limit htaccess allocate php memory

unlimited - Captura de forma segura un error de ''Tamaño de memoria permitido agotado'' en PHP



php memory_limit recommended value (4)

Tengo un script de puerta de enlace que devuelve JSON al cliente. En el script utilizo set_error_handler para detectar errores y todavía tengo un retorno formateado.

Está sujeto a errores de ''Capacidad de memoria agotada'', pero en lugar de aumentar el límite de memoria con algo como ini_set (''memory_limit'', ''19T'') , solo quiero devolver que el usuario debería probar algo más porque solía usar mucho memoria.

¿Hay alguna buena forma de detectar errores fatales?


Si bien la solución @ alain-tiemblo funciona a la perfección, puse este script para mostrar cómo se puede reservar memoria en un script php, fuera del alcance del objeto:

<?php function getMemory(){ return ((int) (memory_get_usage() / 1024)) . ''KB''; } // memory is an object and it is passed by reference function shutdown($memory) { echo ''Start Shut Down: '' . getMemory() . PHP_EOL; // unsetting $memory does not free up memory // I also tried unsetting a global variable which did not free up the memory unset($memory->reserve); echo ''End Shut Down: '' . getMemory() . PHP_EOL; } echo ''Start: '' . getMemory() . PHP_EOL; $memory = new stdClass(); // reserve 3 mega bytes $memory->reserve = str_repeat(''❤'', 1024 * 1024); echo ''After Reserving: '' . getMemory() . PHP_EOL; unset($memory); echo ''After Unsetting: '' . getMemory() . PHP_EOL; $memory = new stdClass(); // reserve 3 mega bytes $memory->reserve = str_repeat(''❤'', 1024 * 1024); echo ''After Reserving again: '' . getMemory() . PHP_EOL; // passing $memory object to shut down function register_shutdown_function(''shutdown'', $memory);

Y la salida sería:

Start: 349KB After Reserving: 3426KB After Unsetting: 349KB After Reserving again: 3426KB Start Shut Down: 3420KB End Shut Down: 344KB


Si necesita ejecutar el código comercial cuando ocurre este error (registro, copia de seguridad del contexto para futuros errores, correos electrónicos u otros), registrar una función de apagado no es suficiente: debe liberar memoria de alguna manera.

Una solución es asignar memoria de emergencia en alguna parte:

public function initErrorHandler() { // This storage is freed on error (case of allowed memory exhausted) $this->memory = str_repeat(''*'', 1024 * 1024); register_shutdown_function(function() { $this->memory = null; if ((!is_null($err = error_get_last())) && (!in_array($err[''type''], array (E_NOTICE, E_WARNING)))) { // $this->emergencyMethod($err); } }); return $this; }


podría obtener el tamaño de la memoria que ya consumió el proceso al usar esta función memory_get_peak_usage documentations en http://www.php.net/manual/en/function.memory-get-peak-usage.php Creo que sería será más fácil si puede agregar una condición para redirigir o detener el proceso antes de que el proceso alcance el límite de memoria. :)


Como sugiere esta respuesta , puede usar register_shutdown_function() para registrar una devolución de llamada que verificará error_get_last() .

Aún tendrá que administrar la salida generada por el código ofensivo, ya sea por el operador @ ( shut up ), o ini_set(''display_errors'', false)

ini_set(''display_errors'', false); error_reporting(-1); set_error_handler(function($code, $string, $file, $line){ throw new ErrorException($string, null, $code, $file, $line); }); register_shutdown_function(function(){ $error = error_get_last(); if(null !== $error) { echo ''Caught at shutdown''; } }); try { while(true) { $data .= str_repeat(''#'', PHP_INT_MAX); } } catch(/Exception $exception) { echo ''Caught in try/catch''; }

Cuando se ejecuta, esta salida es Caught at shutdown . Desafortunadamente, el objeto de excepción ErrorException no se lanza porque el error fatal desencadena la terminación del script, atrapado posteriormente solo en la función de apagado.

Puede verificar la matriz $error en la función de apagado para obtener detalles sobre la causa y responder en consecuencia. Una sugerencia podría ser volver a enviar la solicitud a su aplicación web ( en una dirección diferente, o con diferentes parámetros, por supuesto ) y devolver la respuesta capturada.

Sin embargo, recomiendo mantener error_reporting() alto ( un valor de -1 ) y usar ( como otros han sugerido ) el manejo de errores para todo lo demás con set_error_handler() y ErrorException .