it-swarm.com.de

Verdutzt: PHP Schwerwiegender Fehler: Exception ohne Stack-Frame in Unknown in Zeile 0 ausgelöst?

Ich habe festgestellt, dass ein häufiger Grund für den Fehler eine Ausnahme, die in einem Ausnahmehandler ausgelöst wird ist. Ich bin mir ziemlich sicher, dass dies in der Anwendung, die ich zu debuggen versuche, nicht vorkommt.

Dies kann anscheinend auch passieren, weil einige Dinge können nicht serialisiert werdenin einer Sitzung gespeichert werden . Diese Anwendung speichert höchstens Arrays in der Sitzung (ziemlich viel), aber ich bin zuversichtlich, dass sie nichts Ungewöhnliches speichert.

Jemand bemerkte, dass es ihnen passiert sei, weil ihr Primärschlüssel musste CHAR (32) anstelle von INT (11) sein . Die PKs in dieser App sind alle INTs.

Andere Vorschläge sind, dass es ein Problem mit PHP 5.3.3behoben in 5.3.6 , vollständige Festplatte und einem _ geben könnte. muss einen SimpleXML-Wert typisieren . Wir führen gerade PHP 5.3.3 aus, aber in diesem Fall müsste ein Upgrade der letzte Ausweg sein. Das hat es nicht immer getan.

UPDATE/HINWEIS: Ich kann den Fehler nicht selbst reproduzieren, sondern sehe ihn nur in den Protokollen. Im folgenden Abschnitt wird beschrieben, wo ich glaube den Fehler mache ...

* Aus den Fehlerprotokollen geht hervor, dass mindestens ein Ort, an dem dies geschieht, index.php ist. Ich leite dies nur ab, weil es in einigen Einträgen durch eine verweisende URL angegeben ist. Der Try/Catch-Code befindet sich derzeit nur um den "oberen" Initialisierungsteil des Skripts, darunter befindet sich meist die HTML-Ausgabe. Die Ausgabe enthält PHP Code (allerdings ziemlich unkompliziert), daher muss ich diesen möglicherweise testen. Hier ist der catch-Teil, der keine Ausgabe in den Protokollen erzeugt:

} catch (Exception $e) {
    error_log(get_class($e)." thrown. Message: ".$e->getMessage(). "  in " . $e->getFile() . " on line ".$e->getLine());
    error_log('Exception trace stack: ' . print_r($e->getTrace(),1));
}

Würde mich über Tipps dazu wirklich freuen!

EDIT: PHP wird als Apache-Modul ausgeführt (Server-API: Apache 2.0-Handler). Ich glaube nicht, dass es irgendwelche PHP Beschleuniger gibt, aber es könnte einfach sein, dass ich nicht weiß, wie ich es sagen soll. Keiner der in Wikipedia gelisteten ist in phpinfo () enthalten.

Soweit ich das beurteilen kann ist das MPM prefork. Dies ist das erste Mal, dass ich mich mit MPM befasst habe:

# ./httpd -l
Compiled in modules:
  core.c
  prefork.c
  http_core.c
  mod_so.c
32
groovenectar

Das Problem

Kurz gesagt, Sie haben eine Ausnahme irgendwo geworfen, Sie haben keine Ahnung, wo und bisher konnten Sie den Fehler nicht reproduzieren: Er tritt nur für einige Leute auf, aber nicht für Sie. Sie wissen, dass dies für andere Personen der Fall ist, weil Sie dies in den Fehlerprotokollen sehen.

Reproduzieren Sie das Problem

Da Sie die häufigsten Gründe bereits beseitigt haben, müssen Sie den Fehler reproduzieren. Wenn Sie wissen, welcher Parameter den Fehler verursacht, sollte es leicht sein, den Fehler zu finden.

  • Wahrscheinlich reicht es aus, wenn Sie alle POST/GET-Parameter kennen.
  • Wenn Sie nicht nur mit diesen reproduzieren können, müssen Sie zusätzliche Anforderungsheader kennen. Wie User Agent, Accept-Encoding, ...
  • Wenn Sie immer noch nicht reproduzieren können, wird es sehr schwierig: Der Fehler kann von einem Status (einer Sitzung), der aktuellen Uhrzeit, der Quell-IP-Adresse oder Ähnlichem abhängen.

Die benutzerdefinierte Protokollmethode

Fangen wir einfach an: Um alle Parameter zu erhalten, können Sie ganz am Anfang der betroffenen PHP-Datei etwas schreiben:

file_put_contents("/path/to/some/custom_error_log", date()."\n".print_r(get_defined_vars(), true), FILE_APPEND | LOCK_EX);

Vergessen Sie nicht, dass die Datei custom_error_log für Ihre PHP-Anwendung schreibbar sein muss. Wenn der Fehler dann im Fehlerprotokoll auftritt, suchen Sie die entsprechenden Zeilen in Ihrer Datei custom_error_log. Hoffentlich gibt es nicht zu viele Anfragen pro Sekunde, sodass Sie die Anfrage immer noch identifizieren können. Möglicherweise helfen einige zusätzliche Parameter im Fehlerprotokoll, wie die Quell-IP-Adresse, bei der Identifizierung der Anforderung (wenn Ihr Fehlerprotokoll dies anzeigt) ..__ Rekonstruieren Sie aus diesen Daten eine Anforderung mit denselben POST/GET-Parametern.

Die tcpdump-Methode

Die nächste Option, die ebenfalls sehr einfach ist, jedoch Root-Zugriff auf Ihrem Zielcomputer erfordert, ist die Installation von tcpflow. Dann erstellen Sie einen Ordner, cd in diesem Ordner und führen Sie einfach (als root) tcpflow "port 80" aus. Die Option (Port 80) ist ein PCAP-Filterausdruck. Alles, was Sie damit machen können, finden Sie unter man pcap-filter. Diese Filterausdrücke können eine Menge tun.

Jetzt zeichnet tcpflow alle TCP-Verbindungen auf Port 80 auf, rekonstruiert den vollständigen Datenaustausch durch Kombinieren der Pakete, die zu einer Verbindung gehören, und speichert diese Daten in eine Datei. Dabei werden zwei neue Dateien pro Verbindung erstellt, eine für eingehende und eine für ausgehende Daten. Suchen Sie nun die Dateien für eine Verbindung, die einen Fehler verursacht hat, und zwar erneut basierend auf dem Zeitstempel in Ihrem Fehlerprotokoll und dem zuletzt geänderten Zeitstempel der Dateien. Dann erhalten Sie die vollständigen http-Request-Header. Sie können die HTTP-Anforderung jetzt vollständig rekonstruieren, einschließlich der gleichen Akzeptierungscodierung, des Benutzeragenten usw. Sie können die Anforderung sogar direkt an netcat weiterleiten und die genaue Anforderung wiedergeben. Beachten Sie jedoch, dass einige Argumente wie eine Sitzungs-ID Ihnen möglicherweise im Weg stehen. Wenn PHP feststellt, dass eine Sitzung abgelaufen ist, erhalten Sie möglicherweise eine Weiterleitung zu einem Login oder etwas anderem, was unerwartet ist. Möglicherweise müssen Sie Dinge wie die Sitzungs-ID austauschen.

Spottend mehr Sachen

Wenn dies alles nicht hilft und Sie den Fehler auf Ihrem Computer nicht reproduzieren können, können Sie versuchen, alles zu verspotten, was schwer zu verspotten ist. Zum Beispiel die Quell-IP-Adresse. Dies kann einige Stunts erforderlich machen, ist jedoch möglich: Sie können sich mithilfe von ssh mit der Option "-w" mit Ihrem Server verbinden, um eine Tunnelschnittstelle zu erstellen. Weisen Sie dann die fehlerhafte IP-Adresse Ihrem eigenen Computer zu und legen Sie Regeln für die Routing-Route (Route hinzufügen, Host) fest, um den Tunnel für die bestimmte IP-Adresse zu verwenden. Wenn Sie die beiden Computer direkt miteinander verkabeln können, können Sie dies sogar ohne Tunnel tun.

Machen Sie sich keine Mühe, die Sitzung zu verspotten, die am ehesten sein sollte. Sie können alle Sitzungsvariablen mit der Methode mit print_r (get_defined_vars ()) lesen. Dann müssen Sie eine Sitzung mit den gleichen Variablen erstellen.

Fragen Sie den Benutzer

Eine andere Möglichkeit wäre, den Benutzer zu fragen, was er gerade macht. Vielleicht können Sie den gleichen Schritten wie er folgen und sich reproduzieren.Wenn nichts davon hilft.

Wenn nichts davon hilft ... naja ... dann wird es ernsthaft schwierig. Das IP-Ding ist schon sehr unwahrscheinlich. Es könnte eine GEO-IP-Bibliothek sein, die den Fehler bei IPs aus einer bestimmten Region verursacht. Dies ist jedoch alles eher unwahrscheinlich. Wenn keine der oben genannten Punkte Ihnen dabei behilflich war, das Problem zu reproduzieren, haben Sie wahrscheinlich nicht die richtige Anforderung in allen Daten gefunden, die von custom_log_file-call/tcpflow generiert wurden. Versuchen Sie, Ihre Chancen zu erhöhen, indem Sie einen genaueren Zeitstempel erhalten. Sie können microtime () in php als Ersatz für date () verwenden. Überprüfen Sie Ihren Webserver, ob Sie in Ihrem Fehlerprotokoll etwas genaueres als Sekunden finden können. Schreiben Sie Ihre eigene Implementierung von "tail", die Ihnen einen genaueren Zeitstempel gibt, ... Reduzieren Sie die Systemlast, sodass Sie nicht aus so vielen Daten wählen müssen (versuchen Sie es mit einer anderen Uhrzeit, Benutzerlast) auf verschiedene Server, ...)

Kreisen Sie das Problem ein, sobald Sie es reproduzieren können

sobald Sie sich reproduzieren können, sollte es ein Spaziergang im Park sein, um die eigentliche Ursache herauszufinden. Sie finden den Parameter, der den Fehler verursacht, durch Ausprobieren und Vergleichen, indem Sie ihn mit anderen Anforderungen vergleichen, die ebenfalls einen Fehler verursacht haben, und nach Ähnlichkeiten suchen. Und dann können Sie sehen, was dieser Parameter bewirkt, welche Bibliotheken darauf zugreifen usw. Sie können jede Komponente nacheinander deaktivieren, die den Parameter verwendet, bis Sie nicht mehr reproduzieren können. Dann hast du deine Komponente und kannst tiefer in das Problem eintauchen.

Sag uns, was du gefunden hast. Ich bin neugierig ;-).

Tell us what you found. I am curious ;-).

18
yankee

Ich hatte auch einen solchen Fehler. Ich habe herausgefunden, dass ich ein SQL-Objekt in meiner Session-Klasse zurückgegeben habe (das vom session_handler verwendet wurde), anstatt nichts oder zumindest nicht das SQL-Objekt zurückzugeben. Sehen Sie sich zuerst Ihre _write- und _read-Methoden an, wenn Sie auch falsches Material zurückgeben.

Hinweis: ... Unbekannt in Zeile 0 - So finden Sie die richtige Zeile, es ist NICHT "Zeile 0"

4
djot

Was passiert, wenn Sie einen Ausnahmebehandler registrieren, anstatt Code in einen try/catch-Block zu packen? Ihr Try/Catch-Block fängt natürlich nicht die Ausnahme ab, was dazu führt, dass die Fehler in Apache protokolliert werden. Durch die Registrierung eines Handlers können Sie sicher sein, dass alle nicht erfassten Ausnahmen behandelt werden.

Wenn Sie in Ihrer Anwendung Namespaces verwenden, müssen Sie sicherstellen, dass Sie\Exception in den catch-Block schreiben (oder die Exception-Klasse über eine use-Anweisung einschließen).

3
Peter Kruithof

Für uns lag dieser Fehler daran, dass versehentlich SimpleXML-Objekte serialisiert wurden. 

Wenn Sie SimpleXML-Objekte mit 5.3.3 verwenden, stellen Sie sicher, dass Sie die Knotenwerte in das, was Sie benötigen, umwandeln (z. B. Zeichenfolge), wenn Sie die Werte in der Sitzung serialisieren.

Vor :

  $token = $response->Token->Value;
  /* token saved in session, results in line 0 error */

Nach dem :

$token = (string) $response->Token->Value;
  /* token saved in session, no error */
2
David

Ich weiß, dass diese Frage bereits beantwortet wurde, aber ich werde dies hinzufügen, da es jemandem helfen kann:

Es ist mir (unbeabsichtigt) gelungen, Fehler ohne einen Stackframe aus einer Funktion zu erzeugen, die ihren eigenen Fehlerhandler verwendet, um die Ausführung der Steuerung zu erhalten, während sie eine potenziell "gefährliche" Funktion aufrufen, wie folgt:

// Assume the function my_error_handler() has been defined to convert any
// PHP Errors, Warnings, or Notices into Exceptions.

function foo() {
    // maintain control if danger() crashes outright:
    set_error_handler('my_error_handler');

    try {
        // Do some stuff.

        $r = danger();
    } catch (Exception $e) {
        $r = 'Bad Stuff, Man!';
    }

    restore error_handler();
    return $r;
}

Der "nicht nachvollziehbare Fehler" würde am Ende der Programmausführung auftreten, wenn die Logik in "Do some stuff" direkt von foo () zurückkehrt und den Aufruf von restore_error_handler () umgeht. Was ich von dieser Erfahrung mitgenommen habe, ist folgendes:

  1. PHP unterhält ein stack von Fehlerbehandlern, das mit jedem Aufruf von set_error_handler () tiefer/höher wird.
  2. Bad Stuff kann auftreten, wenn Sie Fehlerbehandlungsroutinen auf den Stapel schieben und nicht bereinigen, bevor das Programm "normal" beendet wird.

Dies war ein schwieriger Fehler, den ich isolieren konnte. Ich beschränkte das Problem auf die obige Funktion und starrte es an, bis meine Augen bluteten.

Wie hätte ich das ausfindig machen können und wissen, was ich jetzt weiß? Da mir keine Möglichkeit bekannt ist, den PHP - Fehlerbehandlungsstapel "Stack" direkt zu untersuchen, denke ich, dass es sinnvoll sein könnte, ein Singleton-Objekt zu verwenden, um alle Set/Restore-Vorgänge für PHP einzukapseln. Fehlerbehandler. Zumindest wäre es dann möglich, den Status des Singleton zu überprüfen, bevor das Programm normal beendet wird, und wenn "fehlerhafte" Fehlerbehandlungsroutinen erkannt werden, um eine vernünftige Fehler-/Warnmeldung zu erzeugen, bevor PHP ausfällt.

2
Peter

Dies ist möglicherweise etwas spät, aber ein Problem, das ich beim Verschieben einer Site von einem lokalen Server auf einen Remote-Server festgestellt habe. Ich verwendete Concrete5 cms, hatte meine Site lokal entwickelt (Windows 8 in xampp) und dann auf einen Remote-Server hochgeladen, auf dem Cent 0S ausgeführt wurde

Windows mysql ist standardmäßig unabhängig von der Groß- und Kleinschreibung und erstellt eine Datenbank mit Kleinbuchstaben. Nachdem dies auf den Remote-Server hochgeladen wurde, erhielt ich die "Ausnahme ohne Stack-Frame in Unknown in Zeile 0?"

Ich korrigierte dann den Fall der Datenbanktabellen und meine Site funktionierte wieder.

2
Sean

Ich hatte den gleichen Fehler, nachdem ich die Fillable-Eigenschaft des Illuminate Eloquent-Modells falsch ausgefüllt hatte. Beachten Sie die letzten 3 Elemente des Arrays, eines ist ohne Koma.

protected $fillable = [
    'budget',        
    'routestatus' ,
    'userroutenumber'
    'totalmovingseconds',
    'totalidleseconds'
];
1
Dennis Berg

Ich hatte völlig den gleichen Fehler. Ein ganz besonderer Fall: Wenn Sie einen unbenannten Funktionshaken (Schließung) an einen Hook-Punkt einer Objektinstanz anschließen. Danach versuchen Sie, dieses Objekt zu serialisieren. 

0
Akos

Dieses Problem trat für mich auf, als ich den Namespace einiger Symfony-Bundles geändert habe. Das Löschen der Dateien im Symfony-Cache-Verzeichnis hat das Problem behoben.

0
ssjcory

Wahrscheinlich haben Sie eine beschädigte/inkonsistente Tabelle in der Datenbank. Versuchen Sie, die Datenbank zu sichern. Wenn Sie einen Fehler erhalten, ist dies die Zeit. Reparieren Sie diesen Tisch und das Problem sollte verschwinden.

Aus diesem Grund funktioniert die saubere Installation. Die saubere Installation ist einfach so sauber.

mysqlcheck sollte funktionieren, aber wenn es nicht angezeigt wird, tun Sie es weiter oben.

0
Roland Booth

ein einfacher Weg, diesen Fehler zu erzeugen, ist ein alter Server mit register_globals = On. dann brauchen Sie nur zwei Codezeilen:

<?php
    $_SESSION["my_var"] = "string";
    $my_var = new MyClass(); //could be any class, i guess
?>

sobald Sie diese Seite einmal neu laden, wird die Exception thrown without a stack frame in Unknown on line 0 - Fehlermeldung angezeigt. scheint ein Konflikt zwischen der Instanz der Klasse und der (session) -Variablen zu bestehen.
Zumindest habe ich diesen nervigen Fehler bekommen, der so schwer zu debuggen ist.

0
low_rents

Ich hatte den gleichen Fehler, es schien, als würde ich den Server von Centos 5 auf Centos 6 aktualisieren und PHP von 5.4 auf 5.3 herabstufen. Das aktuelle Problem war PHP apc und wurde nicht ordnungsgemäß konfiguriert. Überprüfen Sie Ihren APC. Ich habe Symfony2 verwendet, daher finden Sie möglicherweise Hilfe unter Symfony Speicher kann nicht für Pool zugewiesen werden

0
cargan