Lösung für "Schwerwiegender Fehler: Maximale Funktionsverschachtelung von '100' erreicht, Abbruch!" in PHP

137

Ich habe eine Funktion erstellt, die alle URLs in einer HTML-Datei findet und denselben Vorgang für jeden HTML-Inhalt wiederholt, der mit den erkannten URLs verknüpft ist. Die Funktion ist rekursiv und kann endlos fortgesetzt werden. Ich habe jedoch die Rekursion begrenzt, indem ich eine globale Variable festgelegt habe, die bewirkt, dass die Rekursion nach 100 Rekursionen gestoppt wird.

PHP gibt jedoch diesen Fehler zurück:

Schwerwiegender Fehler: Maximale Funktionsverschachtelungsstufe von '100' erreicht, Abbruch! in D: \ wamp \ www \ crawler1 \ simplehtmldom_1_5 \ simple_html_dom.php in Zeile 1355

ERROR

Ich habe hier eine Lösung gefunden: Das Limit für Aufrufe von Verschachtelungsfunktionen wird erhöht, aber dies funktioniert in meinem Fall nicht.

Ich zitiere eine der Antworten aus dem oben genannten Link. Bitte bedenken Sie es.

"Haben Sie Zend, IonCube oder xDebug installiert? Wenn ja, erhalten Sie diesen Fehler wahrscheinlich von dort.

Ich bin vor ein paar Jahren darauf gestoßen, und am Ende hat Zend diese Grenze gesetzt, nicht PHP. Wenn Sie es entfernen, können Sie natürlich die 100 Iterationen überschreiten, aber Sie werden schließlich die Speichergrenzen erreichen. "

Gibt es eine Möglichkeit, die maximale Funktionsverschachtelung in PHP zu erhöhen?

Rafay
quelle
2
Außerdem: PHP hat keine Begrenzung für verschachtelte Funktionsaufrufe. Es muss eine Erweiterung sein, die Sie verwenden, die dies verursacht.
Abel
@Abel Ich bin sicher, dass mein Code keine Fehler enthält. Es gibt eine statische Variable, die ihren Wert bei jedem rekursiven Aufruf um eins erhöht. Wenn diese Variable kleiner als 100 ist, werden die rekursiven Aufrufe fortgesetzt, bis die Variable 100 erreicht. Ich meine zu sagen, dass die Variable, die 100 erreicht, tatsächlich der Basisfall ist. Während der Fehler vor 100 Rekursionen auftritt. Und da Sie erwähnt haben, dass eine Erweiterung dies verursacht, möchte ich erwähnen, dass ich Funktionen aus simple_html_dom.php verwende. Wenn Sie eine Idee zu simple_html_dom.php haben, helfen Sie mir bitte in dieser Hinsicht. Bitte beziehen Sie sich auf die aktualisierte Frage.
Rafay
7
Das ist ein Fehler von xdebug. Aus dem Screenshot geht hervor, dass Sie xdebug verwenden. Sie können die Einstellung hier deaktivieren: xdebug.max_nesting_level oder angeben , wie groß die Verschachtelungsebene ist.
hakre
3
Wenn Sie WAMP verwenden, beachten Sie, dass das Deaktivieren von xdebug in php.ini NICHT immer funktioniert. Gleiches gilt für die Erweiterung des zulässigen Verschachtelungsniveaus. ein Fehler eine Vermutung; LÖSUNG: Gehen Sie zu php.ini und kommentieren Sie php_xdebug - ???. Dll
Jeffz

Antworten:

145

Erhöhen Sie den Wert von xdebug.max_nesting_levelin Ihremphp.ini

Maxence
quelle
6
@AL Sie bearbeiten Ihre Datei php.ini und fügen die Zeile xdebug.max_nesting_level im Abschnitt XDebug hinzu oder bearbeiten sie.
Maxence
3
Wenn es sich jedoch um eine Produktionsumgebung handelt, lesen Sie die akzeptierte Antwort, nämlich xdebug in dieser Umgebung zu deaktivieren.
zkent
3
Dies löst das Symptom (für eine Weile), aber nicht das Problem.
Sebastian Mach
1
Diese Lösung hat bei mir funktioniert, als ich UFront für Haxe auf MAMP verwendet habe.
Vertrauter
4
für unbegrenzte:xdebug.max_nesting_level = -1
Nabi KAZ
55

Eine einfache Lösung löste mein Problem. Ich habe gerade diese Zeile kommentiert:

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

in meiner php.iniAkte. Diese Erweiterung beschränkte den Stapel auf, 100sodass ich ihn deaktivierte. Die rekursive Funktion funktioniert jetzt wie erwartet.

Rafay
quelle
4
Schließlich war es schließlich die XDebug-Erweiterung ... Gut zu wissen. In zwei Tagen können Sie Ihre eigene Antwort als akzeptierte Antwort akzeptieren, wenn Sie möchten (und sich Ihre vorherigen Fragen ansehen, die meisten verpassen eine akzeptierte Antwort).
Abel
61
Der Umgang mit der übermäßigen Rekursion ist sicherlich besser, als nur die Überwachung auszuschalten.
Peteis
7
Das ist ein hartnäckiger Ansatz. Die obigen Antworten, in denen die Variable zum Anpassen der maximalen Stapeltiefe erwähnt wird, sind ein besserer Ansatz.
Aredridel
7
Sie sollten xdebug in einer Produktionsumgebung nicht aktiviert haben.
HarryFink
2
Heiliger Strohsack. Ich kann nicht aufhören über die gewählte Lösung zu lachen. Damit mein PC nicht aufhört, Geräusche zu machen, habe ich die Lösung gefunden. Schalte es aus. :)
Kevin Remisoski
44

Arbeiten Sie mit einem Warteschlangenmodell, um die Struktur zu reduzieren, anstatt rekursive Funktionsaufrufe durchzuführen.

$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;
}

Es gibt verschiedene Möglichkeiten, damit umzugehen. Sie können weitere Informationen nachverfolgen, wenn Sie einen Einblick in den Ursprung oder die durchquerten Pfade benötigen. Es gibt auch verteilte Warteschlangen, die mit einem ähnlichen Modell arbeiten können.

Louis-Philippe Huberdeau
quelle
5
Mit SPL müssen Sie die Warteschlange nicht neu erfinden: php.net/manual/en/class.splqueue.php
Francesco
1
Die SPL-Warteschlange bietet möglicherweise etwas mehr Geschwindigkeit, aber ich halte mich bei den meisten einfachen Aufgaben gerne an Arrays. Push / Pop / Shift / Unshift sind alle vorhanden.
Louis-Philippe Huberdeau
1
Dies ist die richtige Antwort. Vermeiden Sie die Änderung der Standardwerte. Versuchen Sie, Ihren Code zu optimieren.
Junaid Atique
41

Eine andere Lösung ist das Hinzufügen xdebug.max_nesting_level = 200in Ihrer php.ini

Bacar Ndiaye
quelle
8
Es ist auch möglich, dies in PHP zu tun, zum Beispiel in der Konfigurationsdatei Ihres Projekts. ini_set('xdebug.max_nesting_level', 200);
Svassr
@htxryan Ich bin kein Experte, aber es liegt daran, dass Ihr Aufrufstapel zu "tief" ist (zu viele Funktionen, die andere Funktionen aufrufen). Das typische Szenario, in dem dies auftritt, ist eine rekursive Funktion. Die Einstellung verhindert dort höchstwahrscheinlich eine "außer Kontrolle geratene" Rekursion aufgrund eines Fehlers im Code.
Bryan
@svassr Vielleicht möchten Sie diesen Tipp als separate Antwort hinzufügen oder zu einer vorhandenen hinzufügen. Es war hilfreich für mich, hat es aber in den Kommentaren fast verpasst
Bryan
@ Bryan hat gerade eine Antwort hinzugefügt
Svassr
23

Anstatt den xdebug zu deaktivieren, können Sie das höhere Limit wie festlegen

xdebug.max_nesting_level = 500

Shahinam
quelle
@SebastianMach: und erstaunlicherweise auch Jahre später. :) (Wie vier weitere Male oder so. Die Leute lesen jetzt nicht nur nicht, sie scrollen nicht einmal mehr.)
Gr.
1
@Sz.: Wow, was für eine Explosion aus der Vergangenheit: P Erstaunlich schockierend.
Sebastian Mach
18

Es ist auch möglich, dies direkt in PHP zu beheben, beispielsweise in der Konfigurationsdatei Ihres Projekts.

ini_set('xdebug.max_nesting_level', 200);

svassr
quelle
1
Danke, das funktioniert gut, da ich mir keine Sorgen um die Aktualisierung von php.ini auf allen meinen Entwicklungsboxen machen muss. Ich füge dies einfach der Bootstrap-Datei meiner Anwendung hinzu.
Bryan
13

Gehen Sie in Ihre Konfigurationsdatei php.ini und ändern Sie die folgende Zeile:

xdebug.max_nesting_level=100

zu so etwas wie:

xdebug.max_nesting_level=200
Yasssine ELALAOUI
quelle
13

unter Ubuntu mit PHP 5.59: muss
zu `:

/etc/php5/cli/conf.d

und finde deine xdebug.ini in diesem Verzeichnis , in meinem Fall ist 20-xdebug.ini

und füge diese Zeile hinzu `

xdebug.max_nesting_level = 200


oder dieses

xdebug.max_nesting_level = -1

Setzen Sie es auf -1 und Sie müssen sich keine Sorgen machen, den Wert der Verschachtelungsebene zu ändern.

`

Gujarat Santana
quelle
12

wahrscheinlich wegen xdebug passiert.

Versuchen Sie, die folgende Zeile in Ihrer "php.ini" zu kommentieren, und starten Sie Ihren Server neu, um PHP neu zu laden.

  ";xdebug.max_nesting_level"

vandersondf
quelle
2
oder deaktiviert alle xdebug
zloctb
2
Wie würde das funktionieren? Wenn Sie das Limit nicht manuell definieren, wird es einfach auf den Standardwert zurückgesetzt, der 100 ist ( xdebug.org/docs/basic ). Wenn Sie diese Zeile auskommentieren, erzwingen Sie lediglich, dass die Einstellung auf die Standardeinstellung zurückgesetzt wird.
Justanotherprogrammer
Das Deaktivieren aller xdebug wird nicht empfohlen, wenn Sie von der Verwendung des Tools abhängen. Normalerweise wird die Konfiguration "xdebug.max_nesting_level" verwendet, ohne seine tatsächliche Verwendung zu kennen, sodass im Allgemeinen nur ein Kommentar ausreicht und gültig ist.
Vandersondf
12

Suchen Sie in /etc/php5/conf.d/ nach einer Datei mit dem Namen xdebug.ini

max_nesting_level ist standardmäßig 100

Wenn es nicht in dieser Datei festgelegt ist, fügen Sie hinzu:

xdebug.max_nesting_level=300

bis zum Ende der Liste, so sieht es aus

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

Sie können dann den Test von @ Andrey vor und nach dieser Änderung verwenden, um festzustellen, ob er funktioniert hat.

php -r 'function foo() { static $x = 1; echo "foo ", $x++, "\n"; foo(); } foo();'
Lee Woodman
quelle
Großartig, die erste Antwort, die erwähnt, dass xdebug eine separate .iniDatei hat. Übrigens, wenn Sie php5-fpm ausführen, ist diese Datei wahrscheinlich irgendwo hier:/etc/php5/fpm/conf.d/20-xdebug.ini
Daan
7

php.ini:

xdebug.max_nesting_level = -1

Ich bin nicht ganz sicher, ob der Wert jemals überlaufen und -1 erreichen wird, aber er wird entweder nie -1 erreichen oder den max_nesting_level ziemlich hoch setzen.

Martyn Shutt
quelle
Es klappt! Egal ob Sie XDebug verwenden oder nicht, auch nicht, wenn Sie die Zeile in der php.ini auskommentieren. Ich habe explizit verwendet: ini_set ('xdebug.max_nesting_level', -1);
user2928048
6

Sie können Ihren rekursiven Code in einen iterativen Code konvertieren, der die Rekursion simuliert. Dies bedeutet, dass Sie den aktuellen Status (URL, Dokument, Position im Dokument usw.) in ein Array verschieben müssen, wenn Sie einen Link erreichen, und ihn aus dem Array entfernen müssen, wenn dieser Link fertig ist.

Yogu
quelle
5

Sie können versuchen, die Verschachtelung zu verringern, indem Sie parallele Worker implementieren (wie beim Cluster-Computing), anstatt die Anzahl der Aufrufe von Verschachtelungsfunktionen zu erhöhen.

Beispiel: Sie definieren eine begrenzte Anzahl von Slots (z. B. 100) und überwachen die Anzahl der "Arbeitern", die jedem / einigen von ihnen zugewiesen sind. Wenn irgendwelche Slots frei werden, setzen Sie die wartenden Arbeiter "in sie".

Tamasgal
quelle
1
Das ist kein allgemein anwendbarer Ansatz. Das Parallelisieren ist sinnvoller, nicht die Stapeltiefe zu vermeiden.
Aredridel
5

Überprüfen Sie die Rekursion über die Befehlszeile:

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

wenn Ergebnis> 100 DANN Speicherlimit prüfen;

Andrey
quelle
3

Wenn Sie Laravel verwenden, tun Sie dies

composer update

Das sollte Arbeit sein.

Putri Dewi Purnamasari
quelle
Sie sollten hierzu weitere Hintergrundinformationen hinzufügen. Dies könnte nützlich sein, obwohl laracasts.com/forum/…
ggderas
1
Dies hat keinen Einfluss auf die Einstellungen von xdebug / php.ini, die die Fehlerursache sein könnten. Es ist auch möglich , dass Sie Anwendung ist in einer DOS - Schleife und kontinuierlich eine Funktion Umschlingung, kein wo hat OP Zustand sie Laravel und Blick auf seinen Code Schluck sein wahrscheinliches codeigniter sein wurden mit
James Kirkby
3
<?php
ini_set('xdebug.max_nesting_level', 9999);
... your code ...

PS Ändern Sie 9999 in eine beliebige Zahl.

Cofirazak
quelle
1

Ich hatte einen Fehler, als ich viele Plugins installiert habe. Der Fehler 100 zeigte also den Speicherort des letzten Plugins an, das ich installiert habe. C: \ wamp \ www \ mysite \ wp-content \ plugins \ "...", also habe ich dieses Plugin gelöscht Ordner auf dem Laufwerk C: dann war alles wieder normal. Ich denke, ich muss die Anzahl der Plug-Ins, die ich installiere oder aktiviert habe, begrenzen. Viel Glück, ich hoffe, es hilft

CalvinMD
quelle
1

In Ihrem Fall hat die Crawler-Instanz definitiv mehr Xdebug-Limit, um Fehler- und Debug-Informationen zu verfolgen.

In anderen Fällen führen jedoch auch Fehler wie bei PHP oder Kerndateien wie CodeIgniter-Bibliotheken zu einem solchen Fall, und wenn Sie die Einstellung für die X-Debug-Ebene sogar erhöhen, verschwindet sie nicht.

Schauen Sie sich also Ihren Code genau an :).

Hier war das Problem in meinem Fall.

Ich hatte eine Serviceklasse, die Bibliothek in CodeIgniter ist. Eine Funktion wie diese haben.

 class PaymentService {

    private $CI;

    public function __construct() {

        $this->CI =& get_instance();

   }

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

Mein Controller wie folgt:

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

Der Funktionsaufruf in der letzten Zeile war wegen des Tippfehlers falsch, stattdessen sollte er wie folgt aussehen:

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

Dann bekam ich immer wieder die Fehlermeldung "Überschreiten". Aber ich habe XDebug deaktiviert, aber nicht geholfen. Überprüfen Sie auf jeden Fall Ihren Klassennamen oder Ihren Code auf ordnungsgemäße Funktionsaufrufe.

Daniel Adenew
quelle
Ist es eine Antwort oder eine Frage?
AL
@daniedad Ich habe Ihre Antwort bearbeitet. Ich denke, es ist besser, die Lösung in Text und nicht nur in Kommentaren zu schreiben, die an den Code angehängt sind. Und die gegenwärtige Form ließ mich denken, dass es eine neue Frage und keine Antwort war. Sie können jederzeit einen Rollback durchführen, wenn Sie die Änderungen ablehnen.
AL
1

Ich hatte dieses Problem mit WordPress auf Cloud9. Es stellte sich heraus, dass es sich um das W3-Caching-Plugin handelte. Ich habe das Plugin deaktiviert und es hat gut funktioniert.

so sei es
quelle
1

Eine andere Lösung, wenn Sie PHP-Skript in CLI (cmd) ausführen

Die zu bearbeitende Datei php.ini ist in diesem Fall anders. In meiner WAMP-Installation lautet die in die Befehlszeile geladene Datei php.ini:

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

anstelle von \ wamp \ bin \ apache \ apache2.4.9 \ bin \ php.ini, das geladen wird, wenn PHP vom Browser ausgeführt wird

Binod Kalathil
quelle
0

Sie können die Funktion {debug} auch in modifier.debug_print_var.php ändern, um die Rekursion in Objekte zu begrenzen.

Um die Linie 45 herum, bevor:

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

Nach dem :

$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));

Auf diese Weise verhält sich Xdebug weiterhin normal: Begrenzen Sie die Rekursionstiefe in var_dump und so weiter. Da dies ein kluges Problem ist, kein Xdebug!

theredled
quelle
0

Ich hatte das gleiche Problem und ich liebe es wie folgt:

Öffnen Sie die MySQL my.ini-Datei

Fügen Sie im Abschnitt [mysqld] die folgende Zeile hinzu: innodb_force_recovery = 1

Speichern Sie die Datei und versuchen Sie, MySQL zu starten

Entfernen Sie die gerade hinzugefügte Zeile und speichern Sie sie

Yassine Ech-Charafi
quelle