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.