2010-02-23 13 views
11

Sai qualsiasi soluzione per recuperare l'errore fatale di PHP: "ammessi dimensione della memoria ... esaurito"Come recuperare da un errore fatale "ammessi memoria dimensioni esausto"

Ho una funzione di spegnimento che viene chiamato quando viene visualizzato un errore irreversibile. Questa funzione crea una ErrorException da esso e la registra.

Il problema è: quando non c'è più memoria disponibile, non è possibile registrare l'errore (accedo a Firebug, tramite FirePHP, con Zend Framework).

Così che cosa intendo per "come recuperare da esso", è come eseguire log degli errori di base, e lasciare che Zend Framework inviare le intestazioni, in modo che l'errore viene registrato (in Firebug nel mio caso) come qualsiasi altro errore?

Grazie

risposta

9

Questo errore è un errore irreversibile, il che significa che non è possibile ripristinare da esso. Se PHP ha raggiunto il suo limite di memoria, non sarà in grado di allocare più memoria per creare l'eccezione e qualsiasi altra memoria di cui ha bisogno per portare a termine la sua esecuzione.

C'è un altro tipo di errore - "errore irreversibile catchable" che, come suggerisce il nome, può essere catturato in un try/catch, ma sfortunatamente l'allocazione delle dimensioni della memoria non è una di queste.

+0

È possibile espandere il limite di memoria durante l'esecuzione? (solo per avere abbastanza memoria per completare il rendering del sito) Suppongo che non sia possibile elencare tutti gli oggetti in memoria e "uccidere" quello che è troppo grande, come avrei potuto con i processi? (So ​​che questo è chiedere la luna, ma chissà) –

+0

Non ci credo. Se si tratta di una cosa particolare che si imbatte in questo problema, allora si dovrebbe semplicemente evitare il problema e aumentare il limite di memoria (per quello script). Non è quello che vuoi, ma non credo che tu abbia altra scelta. –

+0

No 'sfavorevole no. Solo per curiosità, quanto è il limite di memoria attuale e che tipo di sito web è? Non sono sicuro di quale sia l'importo consigliato, ma tendo ad impostarlo su 1/4 della RAM sulla macchina. Forse nei punti chiave del tuo script potresti chiamare memory_get_usage e se si sta alzando, aumentare l'impostazione memory_limit prima che entri in funzione? Non sono sicuro senza conoscere il layout e lo scopo del tuo script. –

2

errori PHP vengono inviati per impostazione predefinita per il registro errori apache /path/to/apache/logs/error.log e si può vedere lì.

+0

Per favore perdonami; Apprezzo il tuo aiuto, ma credo di non essere stato chiaro nella mia domanda. Accedo a varie destinazioni, posso leggere l'errore, posso fare un var_dump, ma non voglio, questo è un sito web professionale. Voglio essere in grado di registrare l'errore e svuotare le intestazioni una volta che appare questo errore. –

+0

* "Il problema è: quando non c'è più memoria disponibile, non può registrare l'errore" * Sembrava che volessi registrare l'errore. – nickf

4

Il modo regolare per personalizzare la gestione degli errori è attraverso

set_error_handler - Imposta un errore di funzione di gestore definito dall'utente

La documentazione per questo stato di funzione (sottolineatura mia):

I seguenti tipi di errore non possono essere gestiti con una funzione definita dall'utente: E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR, E_COMPILE_WARN ING e la maggior parte di E_STRICT generati nel file in cui viene chiamato set_error_handler().

Quindi, non funzionerà regolarmente, ma si può provare

A partire dal PHP7, Errori ed eccezioni sono Throwables, in modo da poter prova/prendili:

+0

Sì, questo non funziona per errori irreversibili (E_ERROR.) –

+2

register_shutdown_function è la soluzione che sto usando attualmente, e funziona bene –

+0

@Matthieu Cool so. Felice potrei aiutare. – Gordon

1

Uno mi viene in mente è che quando stai facendo l'operazione intensivo di memoria manualmente interrogazione memory_get_usage() su base regolare (ad esempio ogni ciclo iterativo) e scaricare le intestazioni/errori quando si passa sopra un valore di sicurezza che è inferiore al limite di script. Rallenterà molto la tua sceneggiatura, ma almeno avrai qualcosa in cambio.

Oppure, e potresti non essere in grado di farlo, esegui le cose che richiedono molta memoria come uno script basato su CLI richiamato dal tuo materiale basato sul web usando exec. La parte CLI potrebbe cadere, ma la web part sarà in grado di segnalarci.

+0

Grazie, verificherò la funzione get_memory_usage(), ma voglio un generico soluzione per questo problema, non si tratta di una pagina specifica che richiede molta memoria (io uso gli script CLI, come hai detto, per quello). Quindi non posso controllare get_memory_usage() su base regolare. –

+0

Oops, è 'memory_get_usage()', è passato anni da quando l'ho usato. – Mike

2

Hai un'idea per un trucco non testato e sarei felice di sapere se è stato utile. Assegnare alcune variabili globali quando si registra la funzione di arresto per la prima volta e rilasciata quando viene eseguito per la prima volta il codice della funzione di arresto. È quindi possibile disporre di memoria sufficiente per creare l'oggetto Exception. Fammi sapere se ha funzionato e per favore pubblica il codice qui.

+0

funziona, basta usare get_peak_memory_usage prima e dopo la tua chiamata di eccezione per capire quanta memoria hai bisogno di allocare e impostare una variabile di quella dimensione in $ GLOBALS, quindi disinserirla nella parte superiore della funzione shutdown – profitphp

+0

@profitphp: il la sintassi corretta è memory_get_peak_usage() :) vedi http://php.net/manual/en/function.memory-get-peak-usage.php – hardcoder

1

questo ha funzionato bene per me:

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

Questo presuppone che il limite di memoria è nel formato 123M.

+0

Quando si esegue questo codice? È quando ottieni l'errore fatale? –

+0

Nella funzione shutdown, subito dopo aver determinato che error_get_last() 'non è vuoto. – Tgr

+0

perché si aggiunge la 'M' al metodo 'ini_get()'? – Emma

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

semplicemente dividere la memory_get_usage per 1024 quadrato per confrontarlo con un valore megabyte 'normale' di '70'.

Ho avuto problemi di memoria con php all'interno di un ciclo for e ho scritto questa semplice istruzione if per evitare che il mio script attivasse un errore fatale. Inoltre, il server su cui stavo operando non mi permetteva di modificare il limite di memoria (questo è spesso il caso in alcune offerte cloud come openshift o grandi host web come dreamhost.) Non ho notato alcun serio peggioramento delle prestazioni (in php 5.3 che può gestire funzioni come questa leggermente diverse da php 4.x o 5.x ... in ogni caso l'implicazione delle prestazioni di uno script che dà un errore fatale supera qualsiasi sovraccarico che la chiamata alla funzione può forzare. uno script in fuga dal consumare tutta la RAM disponibile

Molti potrebbero obiettare, oh ehi il tuo software non è ottimizzato Sì. Probabilmente hai ragione, ma con set di dati complessi puoi solo spremere così tante prestazioni prima che sia necessario gettare più memoria su di esso e cercare gli errori di memoria in un flusso di ajax può essere molto frustrante, specialmente quando non si è sicuri di dove siano i propri file di registro.

+0

ottima risposta! proprio quello che stavo cercando ... dovrebbe essersi concentrato di meno nel raccontare una storia personale e più sulla soluzione reale però. Curioso di sapere cosa hai messo nel condizionale. –

Problemi correlati