2010-02-23 20 views
11

¿Conoce alguna solución para recuperarse del error fatal de PHP: "Permitido el tamaño de la memoria ... agotado"Cómo recuperarse de un error grave "Permitido el tamaño de memoria agotada"

que tienen una función de desconexión que se invoca cuando aparece un error fatal. Esta función crea una ErrorException y la registra.

El problema es que cuando no hay más memoria disponible, no puede registrar el error (inicio de sesión en Firebug, a través de FirePHP, con Zend Framework).

Entonces, ¿qué quiero decir con "cómo recuperarse de ella", es la forma de realizar el registro de errores básicos, y dejar que Zend Framework enviar las cabeceras, de modo que se registra el error (en Firebug en mi caso) como cualquier otro error?

Gracias

Respuesta

9

Este error es un error fatal, lo que significa que no puede recuperarse de él. Si PHP ha alcanzado su límite de memoria, no podrá asignar más memoria para crear su excepción y cualquier otra memoria que necesite para llevar a cabo su ejecución.

Hay otro tipo de error: "error fatal capturable" que como su nombre indica, se puede atrapar en un try/catch, pero desafortunadamente la asignación de tamaño de la memoria no es una de ellas.

+0

¿Es posible expandir el límite de memoria durante la ejecución? (solo para obtener suficiente memoria para terminar la representación del sitio) Supongo que no es posible enumerar todos los objetos en la memoria y "matar" el que es demasiado grande, como podría con los procesos? (Sé que esto es pedir la luna, pero quién sabe) –

+0

No lo creo. Si se trata de una cosa en particular que se está metiendo en este problema, entonces quizás deba evitar el problema y aumentar el límite de memoria (para ese script). Que no es lo que quieres, pero no creo que tengas otra opción. –

+0

No 'fraid not. Solo por curiosidad, ¿cuánto es su límite de memoria actual y qué tipo de sitio web es? No estoy seguro de cuál es la cantidad recomendada, pero tiendo a establecerlo en 1/4 de la RAM en la máquina. Tal vez en los puntos clave de su secuencia de comandos pueda llamar a memory_get_usage y si se está volviendo alto, aumente la configuración memory_limit antes de que se dispare. No estoy seguro sin conocer el diseño y el propósito de su secuencia de comandos. –

2

errores de PHP son enviados por defecto para el registro de errores de Apache /path/to/apache/logs/error.log y se puede ver allí.

+0

Por favor, perdóname; Agradezco su ayuda, pero creo que no estaba claro en mi pregunta. Me conecto a varios destinos, puedo leer el error, puedo hacer un var_dump, pero no quiero, este es un sitio web profesional. Quiero poder registrar el error y lavar los encabezados una vez que aparezca este error. –

+0

* "El problema es: cuando no hay más memoria disponible, no puede registrar el error" * Parecía que deseaba registrar el error. – nickf

4

La forma regular para personalizar el control de errores es a través de

set_error_handler - Establece una función de controlador de error definido por el usuario

la documentación para este estado de función (énfasis mío):

Los siguientes tipos de error no pueden manejarse con una función definida por el usuario: E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR, E_COMPILE_WARN ING, y la mayor parte de E_STRICT aparece en el archivo donde se llama a set_error_handler().

Por lo tanto, no va a funcionar con regularidad, pero se puede tratar

A partir de PHP7, errores y excepciones son Throwables, por lo que puede pruébelo/atrápalos:

+0

Sí, esto no funciona para los errores fatales (E_ERROR) –

+2

register_shutdown_function es la solución que estoy utilizando actualmente, y funciona bien –

+0

@Matthieu Cool saber. Feliz yo podría ayudar. – Gordon

1

Uno que se me ocurre es que cuando estás haciendo tu memoria operación intensiva que manualmente consulta memory_get_usage() sobre una base regular (por ejemplo, cada iteración de bucle) y volcar sus encabezados/error cuando rebasa algún valor de seguridad que está por debajo del límite del script. Se ralentizará mucho su script, pero al menos obtendrá algo a cambio.

O, y es posible que no pueda hacer esto, ejecute el material de memoria intensivo como un script basado en CLI desde dentro de su material basado en la web mediante el uso de exec. La parte CLI podría fallar, pero la parte web podrá informar sobre ella.

+0

Gracias, revisaré la función get_memory_usage(), pero quiero un genérico Solución para este problema, no se trata de una página específica que requiere mucha memoria (uso los scripts de la CLI, como dijo, para eso). Entonces no puedo verificar get_memory_usage() regularmente. –

+0

Vaya, es 'memory_get_usage()', ha pasado años desde que usé ese. – Mike

2

Tengo una idea para un truco no probado y me gustaría saber si me ayudó. Asigne una variable global cuando primero registra la función de apagado y libérela cuando se ejecute por primera vez el código de la función de apagado. Puede tener suficiente memoria para crear el objeto Exception. Avíseme si funcionó y publique el código aquí.

+0

esto funciona, solo use get_peak_memory_usage antes y después de su llamada de excepción para averiguar cuánta memoria necesita asignar y establecer una variable de ese tamaño en $ GLOBALS, luego desactívelo en la parte superior de la función de apagado – profitphp

+0

@profitphp: the la sintaxis correcta es memory_get_peak_usage() :) vea http://php.net/manual/en/function.memory-get-peak-usage.php – hardcoder

1

Esto funcionó bien para mí:

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

Esto supone que su límite de memoria está en el formato 123M.

+0

¿Cuándo ejecuta este código? ¿Es cuando tienes el error fatal? –

+0

En la función de apagado, justo después de determinarse que 'error_get_last()' no está vacío. – Tgr

+0

¿por qué anexa el método 'M' on 'ini_get()'? – Emma

7
if((memory_get_usage()/1024 /1024) < 70) 

simplemente dividir el memory_get_usage por 1024 cuadrado para compararlo con un valor 'normal' megabyte de '70'.

Me encontré con problemas de memoria con php dentro de un bucle for y escribí esta simple declaración if para evitar que mi script genere un error fatal. Además, el servidor en el que estaba operando no me permitió modificar el límite de memoria (esto es a menudo el caso en algunas ofertas en la nube como openshift o grandes servidores web como Dreamhost). Realmente no noté ninguna degradación grave del rendimiento (en php 5.3 que maneja funciones como esta ligeramente diferente a php 4.x o 5.x ... en cualquier caso, la implicancia de rendimiento de un script que da un error fatal compensa cualquier sobrecarga que la llamada a la función pueda forzar. Y también evitaría un guión descontrolado al consumir todos los archivos RAM disponibles

Muchos pueden argumentar: oh, su software no está optimizado Sí. Probablemente tenga razón, pero con conjuntos de datos complejos solo puede exprimir tanto rendimiento antes de necesitarlo para arrojar más memoria, y buscar errores de memoria en un flujo de ajax puede ser muy frustrante, especialmente cuando no está seguro de dónde están sus archivos de registro.

+0

¡excelente respuesta! justo lo que estaba buscando ... debería haberse centrado menos en contar una historia personal y más en la solución real. Curioso por saber lo que pones en el condicional. –

Cuestiones relacionadas