Soluzione per "Errore irreversibile: livello massimo di annidamento della funzione di '100' raggiunto, interruzione!” in PHP


138

Ho creato una funzione che trova tutti gli URL all'interno di un file html e ripete lo stesso processo per ogni contenuto html collegato agli URL rilevati. La funzione è ricorsiva e può continuare all'infinito. Tuttavia, ho posto un limite alla ricorsione impostando una variabile globale che provoca l'arresto della ricorsione dopo 100 ricorsioni.

Tuttavia, php restituisce questo errore:

Errore irreversibile: livello massimo di annidamento della funzione di '100' raggiunto, interruzione! in D: \ wamp \ www \ crawler1 \ simplehtmldom_1_5 \ simple_html_dom.php sulla linea 1355

ERRORE

Ho trovato una soluzione qui: aumentare il limite di chiamate della funzione di nidificazione, ma nel mio caso non funziona.

Sto citando una delle risposte dal link sopra menzionato. Per favore, consideralo.

"Hai Zend, IonCube o xDebug installato? In tal caso, probabilmente è da lì che ricevi questo errore.

Mi sono imbattuto in questo alcuni anni fa e alla fine è stato Zend a porre quel limite lì, non PHP. Ovviamente rimuoverlo ti farà superare le 100 iterazioni, ma alla fine colpirai i limiti di memoria ".

C'è un modo per aumentare il massimo livello di annidamento delle funzioni in PHP


2
Inoltre: PHP non ha un limite per le chiamate di funzione nidificate, deve essere un'estensione che stai utilizzando a causare questo.
Abele,

@Abel Sono sicuro che il mio codice non ha errori. C'è una variabile statica che aumenta il suo valore di uno su ogni chiamata ricorsiva. Se quella variabile è inferiore a 100, le chiamate ricorsive continuano fino a quando la variabile raggiunge 100. Voglio dire che la variabile che raggiunge 100 è in realtà il caso base. Mentre l'errore si presenta prima di 100 ricorsioni. E come hai detto che alcune estensioni potrebbero causare questo, vorrei menzionare che sto usando le funzioni di simple_html_dom.php. Se hai qualche idea su simple_html_dom.php, per favore aiutami in questo senso. Si prega di fare riferimento alla domanda aggiornata.
Rafay,

7
Questo è un errore di xdebug. Dallo screenshot è visibile si usa xdebug. Puoi disabilitare l'impostazione qui: xdebug.max_nesting_level o dire quanto è grande il livello di annidamento.
hakre,

3
se usi WAMP, nota che disabilitare xdebug in php.ini NON funziona sempre; lo stesso vale per l'estensione del livello di nidificazione consentita; un bug un'ipotesi; SOLUZIONE: vai su php.ini e commenta php_xdebug - ???. Dll
Jeffz

Risposte:


145

Aumenta il valore di xdebug.max_nesting_levelnel tuophp.ini


6
@AL Modifichi il tuo file php.ini e aggiungi o modifichi la riga xdebug.max_nesting_level nella sezione XDebug.
Maxence,

3
Tuttavia, se si tratta di un ambiente di produzione, vedere la risposta accettata, che è disabilitare xdebug in quell'ambiente.
zkent,

3
Questo risolve il sintomo (per un po '), ma non il problema.
Sebastian Mach,

1
Questa soluzione ha funzionato per me quando usavo UFront per Haxe su MAMP.
Confidente,

4
per illimitato:xdebug.max_nesting_level = -1
Nabi KAZ,

55

Una soluzione semplice ha risolto il mio problema. Ho appena commentato questa riga:

zend_extension = "d:/wamp/bin/php/php5.3.8/zend_ext/php_xdebug-2.1.2-5.3-vc9.dll

nel mio php.inifile. Questa estensione stava limitando lo stack, 100quindi l'ho disabilitato. La funzione ricorsiva ora funziona come previsto.


4
Quindi, alla fine, era l'estensione XDebug dopo tutto ... Buono a sapersi. In due giorni puoi accettare la tua risposta come risposta accettata, se lo desideri (e dai un'occhiata alle tue domande precedenti, la maggior parte perde una risposta accettata).
Abele,

61
Affrontare l'eccessiva ricorsione è sicuramente meglio che semplicemente disattivare il monitoraggio.
petesiss,

7
È un approccio pesante. Le risposte di cui sopra che menzionano la variabile per regolare la profondità massima dello stack è un approccio migliore.
Aredridel,

7
Non hai xdebug abilitato in un ambiente di produzione.
HarryFink,

2
merda santa. Non riesco a smettere di ridere della soluzione scelta. Quindi il mio PC non smetteva di fare rumore, quindi ho trovato la soluzione. Spegnilo. :)
Kevin Remisoski,

44

Invece di cercare una funzione ricorsiva, lavora con un modello di coda per appiattire la struttura.

$queue = array('http://example.com/first/url');
while (count($queue)) {
    $url = array_shift($queue);

    $queue = array_merge($queue, find_urls($url));
}

function find_urls($url)
{
    $urls = array();

    // Some logic filling the variable

    return $urls;
}

Esistono diversi modi per gestirlo. Puoi tenere traccia di ulteriori informazioni se hai bisogno di informazioni sull'origine o sui percorsi attraversati. Esistono anche code distribuite che possono funzionare su un modello simile.


5
Con SPL non è necessario reinventare la coda: php.net/manual/en/class.splqueue.php
Francesco,

1
La coda SPL potrebbe fornire un po 'più di velocità, ma mi piace attenermi agli array per le attività più semplici. push / pop / shift / unshift sono tutti forniti.
Louis-Philippe Huberdeau,

1
Questa è la risposta corretta Evitare di modificare i valori predefiniti. Prova a ottimizzare il tuo codice.
Junaid Atique,

41

Un'altra soluzione è quella di aggiungere xdebug.max_nesting_level = 200php.ini


8
è anche possibile farlo in php, ad esempio nel file di configurazione del tuo progetto. ini_set('xdebug.max_nesting_level', 200);
svassr,

@htxryan Non sono un esperto ma è dovuto al fatto che il tuo stack di chiamate è troppo "profondo" (troppe funzioni che chiamano altre funzioni). Lo scenario tipico in cui ciò si verifica è con una funzione ricorsiva. È molto probabile che l'impostazione sia lì per evitare la ricorsione "fuori controllo" a causa di un bug nel codice.
Bryan,

@svassr potresti prendere in considerazione l'aggiunta di quel suggerimento come risposta separata o l'aggiunta di uno esistente, mi è stato utile, ma è quasi mancato nei commenti
Bryan,

@Bryan ha appena aggiunto una risposta
svassr

23

Invece di disabilitare xdebug, è possibile impostare il limite superiore come

xdebug.max_nesting_level = 500


@SebastianMach: e, sorprendentemente, anche anni dopo. :) (Come altre quattro volte, o giù di lì. Le persone non solo non leggono più adesso, non fanno nemmeno più scorrere.)
Sz.

1
@Sz .: Caspita, che tuffo nel passato: P Incredibilmente scioccante.
Sebastian Mach,

18

È anche possibile risolverlo direttamente in php, ad esempio nel file di configurazione del tuo progetto.

ini_set('xdebug.max_nesting_level', 200);


1
Grazie, funziona bene dato che non devo preoccuparmi di aggiornare php.ini su tutte le mie scatole di sviluppo, aggiungo semplicemente questo al file bootstrap della mia applicazione.
Bryan,

13

Accedi al tuo file di configurazione php.ini e modifica la seguente riga:

xdebug.max_nesting_level=100

a qualcosa come:

xdebug.max_nesting_level=200

13

su Ubuntu usando PHP 5.59:
arrivare a `:

/etc/php5/cli/conf.d

e trova il tuo xdebug.ini in quella directory , nel mio caso è 20-xdebug.ini

e aggiungi questa riga `

xdebug.max_nesting_level = 200


o questo

xdebug.max_nesting_level = -1

impostalo su -1 e non devi preoccuparti di cambiare il valore del livello di annidamento.

`


12

probabilmente è successo a causa di xdebug.

Prova a commentare la seguente riga nel tuo "php.ini" e riavvia il server per ricaricare PHP.

  ";xdebug.max_nesting_level"


2
o disabilitato tutto xdebug
zloctb

2
Come funzionerebbe? Se non si definisce manualmente il limite, verrà ripristinato il valore predefinito, che è 100 ( xdebug.org/docs/basic ). Commentando questa riga, tutto ciò che fai costringe l'impostazione a ripristinare il valore predefinito.
justanotherprogrammer,

Disabilitare tutto xdebug non è raccomandato se si dipende dal suo uso dello strumento; Normalmente la configurazione "xdebug.max_nesting_level" viene utilizzata senza conoscere il suo reale utilizzo, quindi in genere solo un commento è sufficiente e valido.
vandersondf,

12

Prova a cercare in /etc/php5/conf.d/ per vedere se esiste un file chiamato xdebug.ini

max_nesting_level è 100 per impostazione predefinita

Se non è impostato in quel file aggiungere:

xdebug.max_nesting_level=300

alla fine dell'elenco in modo che assomigli a questo

xdebug.remote_enable=on
xdebug.remote_handler=dbgp
xdebug.remote_host=localhost
xdebug.remote_port=9000
xdebug.profiler_enable=0
xdebug.profiler_enable_trigger=1
xdebug.profiler_output_dir=/home/drupalpro/websites/logs/profiler
xdebug.max_nesting_level=300

puoi quindi utilizzare il test di @ Andrey prima e dopo aver apportato questa modifica per vedere se ha funzionato.

php -r 'function foo() { static $x = 1; echo "foo ", $x++, "\n"; foo(); } foo();'

Ottimo, la prima risposta che menziona che xdebug ha un .inifile separato . A proposito quando esegui php5-fpm questo file è probabilmente da qualche parte qui:/etc/php5/fpm/conf.d/20-xdebug.ini
Daan

7

php.ini:

xdebug.max_nesting_level = -1

Non sono del tutto sicuro se il valore traboverà mai e raggiungerà -1, ma o non raggiungerà mai -1, o imposterà il massimo su max_nesting_level.


Funziona! Non importa se usi XDebug o meno, né se commenti la riga in php.ini. Ho usato esplicitamente: ini_set ('xdebug.max_nesting_level', -1);
user2928048

6

È possibile convertire il codice ricorsivo in un codice iterativo, che simula la ricorsione. Ciò significa che è necessario inserire lo stato corrente (url, documento, posizione nel documento, ecc.) In un array, quando si raggiunge un collegamento, e espellerlo dall'array, quando questo collegamento è terminato.


5

Potresti provare a sminuire l'annidamento implementando i lavoratori paralleli (come nel cluster computing) invece di aumentare il numero di chiamate alle funzioni di annidamento.

Ad esempio: si definisce un numero limitato di slot (ad es. 100) e si monitora il numero di "lavoratori" assegnati a ciascuno / alcuni di essi. Se uno slot diventa libero, metti i lavoratori in attesa "in loro".


1
Questo non è davvero un approccio generalmente applicabile. È più sensato parallelizzare, non evitare la profondità dello stack.
Aredridel,

5

Controlla la ricorsione dalla riga di comando:

php -r 'function foo() { static $x = 1; echo "foo ", $x++, "\n"; foo(); } foo();'

se risultato> 100 POI controllare il limite di memoria;


3

Se stai usando Laravel, fallo

composer update

Questo dovrebbe essere lavoro.


È necessario aggiungere ulteriori informazioni di base al riguardo. Questo potrebbe essere utile anche se laracasts.com/forum/…
ggderas,

1
questo non ha alcuna influenza sulle impostazioni di xdebug / php.ini che potrebbero essere la causa dell'errore. È anche possibile che l'applicazione sia in un ciclo DOS e continui a girare attorno a una funzione, in nessun punto in cui OP ha dichiarato che stavano usando laravel e guardando il suo sorso di codice è probabile che sia codeigniter
James Kirkby,

3
<?php
ini_set('xdebug.max_nesting_level', 9999);
... your code ...

PS Cambia 9999 con qualsiasi numero tu voglia.


1

Ho avuto un errore durante l'installazione di molti plug-in Quindi l'errore 100 è stato visualizzato includendo la posizione dell'ultimo plug-in che ho installato C: \ wamp \ www \ mysite \ wp-content \ plugins \ "..." quindi ho eliminato questo plug-in cartella sul disco C: quindi tutto è tornato alla normalità. Penso di dover limitare la quantità di plug-in che installo o ho attivato. Buona fortuna spero che sia di aiuto


1

Nel tuo caso è sicuramente l'istanza del crawler che sta avendo più limite Xdebug per tracciare le informazioni di errore e debug.

Ma, in altri casi, anche errori come su PHP o file core come le librerie CodeIgniter creeranno un caso del genere e se aumenti anche l'impostazione del livello di debug x non svanirà.

Quindi, osserva attentamente il tuo codice :).

Ecco il problema nel mio caso.

Ho avuto una classe di servizio che è libreria in CodeIgniter. Avere una funzione dentro come questa.

 class PaymentService {

    private $CI;

    public function __construct() {

        $this->CI =& get_instance();

   }

  public function process(){
   //lots of Ci referencing here...
   }

Il mio controller come segue:

$this->load->library('PaymentService');
$this->process_(); // see I got this wrong instead  it shoud be like 

La chiamata di funzione sull'ultima riga era errata a causa dell'errore di battitura, invece avrebbe dovuto essere come di seguito:

$this->Payment_service->process(); //the library class name

Quindi continuavo a ricevere il messaggio di errore superato. Ma ho disabilitato XDebug ma non ho aiutato. In ogni caso, controlla il nome della tua classe o il tuo codice per una corretta chiamata della funzione.


È una risposta o una domanda?
AL

@daniedad Ho modificato la tua risposta, penso che sia meglio scrivere la soluzione in testo e non solo nei commenti allegati al codice. E la forma attuale mi ha fatto pensare che fosse una nuova domanda e non una risposta. Sentiti libero di eseguire il rollback se non approvi le modifiche.
AL

1

Ho avuto questo problema con WordPress su cloud9. Si è scoperto che era il plug-in W3 Caching. Ho disabilitato il plugin e ha funzionato bene.


1

Un'altra soluzione se si esegue script php in CLI (cmd)

Il file php.ini che deve essere modificato è diverso in questo caso. Nella mia installazione di WAMP il file php.ini che viene caricato nella riga di comando è:

\wamp\bin\php\php5.5.12\php.ini

invece di \ wamp \ bin \ apache \ apache2.4.9 \ bin \ php.ini che si carica quando php viene eseguito dal browser


0

Puoi anche modificare la funzione {debug} in modifier.debug_print_var.php, al fine di limitare la sua ricorsione in oggetti.

Intorno alla linea 45, prima di:

$results .= '<br>' . str_repeat('&nbsp;', $depth * 2)
  . '<b> -&gt;' . strtr($curr_key, $_replace) . '</b> = '
  . smarty_modifier_debug_print_var($curr_val, ++$depth, $length);

Dopo :

$max_depth = 10;
$results .= '<br>' . str_repeat('&nbsp;', $depth * 2)
  . '<b> -&gt;' . strtr($curr_key, $_replace) . '</b> = '
  . ($depth > $max_depth ? 'Max recursion depth:'.(++$depth) : smarty_modifier_debug_print_var($curr_val, ++$depth, $length));

In questo modo, Xdebug continuerà a comportarsi normalmente: limitare la profondità di ricorsione in var_dump e così via. Dato che questo è un problema intelligente, non Xdebug!


0

Ho avuto lo stesso problema e reslove in questo modo:

Apri il file MySQL my.ini

Nella sezione [mysqld], aggiungi la seguente riga: innodb_force_recovery = 1

Salvare il file e provare ad avviare MySQL

Rimuovi quella riga che hai appena aggiunto e salva

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.