18 Stimmen

Warum enthält debug_backtrace() manchmal keine Zeilennummer?

Ich stelle fest, dass manchmal debug_backtrace() die Leitungsnummer für einen Anruf nicht enthält. Gibt es einen Grund, warum dies so ist, und eine Möglichkeit, dies zu korrigieren?

Vielen Dank im Voraus.

P.S. Und ja, die Aufrufe, bei denen Zeilennummern weggelassen werden, sind mein eigener Code, nicht der interne PHP-Code.

16voto

Dariusz Walczak Punkte 4618

Beachten Sie den folgenden Code:

<?
class BtTest
{
  public function getTheItem()
  {
    var_dump( debug_backtrace( false ) );
    $bt = debug_backtrace( false );
    return $bt[1];
  }

  public function __call( $methodName, $methodArgs )
  {
    return $this->getTheItem();
  }
}

$o = new BtTest();
$bti = $o->test();

assert( 'array_key_exists("function", $bti)' );
assert( 'array_key_exists("line", $bti)' );
assert( 'array_key_exists("file", $bti)' );

Die Ausführung des obigen Beispiels erzeugt folgende Ausgabe:

array(3) {
  [0]=>
  array(6) {
    ["file"]=>
    string(53) "/somewhere/in/the/filesystem/tests/bt-test-so.php"
    ["line"]=>
    int(13)
    ["function"]=>
    string(10) "getTheItem"
    ["class"]=>
    string(6) "BtTest"
    ["type"]=>
    string(2) "->"
    ["args"]=>
    array(0) {
    }
  }
  [1]=>
  array(4) {
    ["function"]=>
    string(6) "__call"
    ["class"]=>
    string(6) "BtTest"
    ["type"]=>
    string(2) "->"
    ["args"]=>
    array(2) {
      [0]=>
      &string(4) "test"
      [1]=>
      &array(0) {
      }
    }
  }
  [2]=>
  array(6) {
    ["file"]=>
    string(53) "/somewhere/in/the/filesystem/tests/bt-test-so.php"
    ["line"]=>
    int(18)
    ["function"]=>
    string(4) "test"
    ["class"]=>
    string(6) "BtTest"
    ["type"]=>
    string(2) "->"
    ["args"]=>
    array(0) {
    }
  }
}
PHP Warning:  assert(): Assertion "array_key_exists("line", $bti)" failed in /somewhere/in/the/filesystem/tests/bt-test-so.php on line 21
PHP Warning:  assert(): Assertion "array_key_exists("file", $bti)" failed in /somewhere/in/the/filesystem/tests/bt-test-so.php on line 22

Das erste Backtrace-Element (Index 0) sagt indirekt (über die line y file Artikel), dass die getTheItem Methode wurde von der __call Methode.

Das zweite Backtrace-Element (Index 1) besagt, dass die __call Methode wurde aufgerufen von irgendwo (fehlt line y file Artikel).

Das dritte Backtrace-Element (Index 2) besagt, dass die test Methode wurde aus dem globalen Bereich des Skripts aufgerufen.

Der Ort des __call Methodenaufruf befindet sich wahrscheinlich in einem Methodenauflösungscode irgendwo im Code des PHP-Interpreters. Es gibt zwei Möglichkeiten, dies zu beheben. Entweder sollte das zweite Element auf die Quellcode-Datei und -Zeile des Interpreters verweisen, oder das zweite und das dritte Backtrace-Element sollten zu einem verschmolzen werden. Ich persönlich würde die zweite Lösung bevorzugen, da die Interna des Interpreters für mich uninteressant sind (so scheinen sie es in Python's Traceback zu machen), jedoch verstehe ich, dass manchmal die erste Lösung eine explizitere Rückverfolgung bietet (besonders wenn es ein Callback ist, der von den Interna aufgerufen wird).

Es scheint also, dass der/die Entwickler, die für den Code des Systems verantwortlich sind (oder ihn zumindest pflegen) debug_backtrace Funktion nicht als Fehler wahrnimmt oder vielleicht keine einfache Möglichkeit hat, ihn zu beheben. Es wäre in Ordnung, die line y file Elemente mit einigen Platzhalterwerten (z. B. <unknown-file> y 0 oder sogar Nullen ) und heben Sie dies in der Dokumentation hervor. Wenn man sie nicht erfolgreich davon überzeugen kann, müssen Sie diesen Sonderfall in Ihrem Code behandeln.

Ich habe oben nur geschrieben, um mein Verständnis für das seltsame Verhalten der Funktion mitzuteilen. Falls jemand bereit ist, für eine etwas bessere Welt zu kämpfen, hier sind Links zu einigen entsprechenden Fehlerberichten:

Der älteste Bericht stammt aus dem Jahr 2003, Sie sollten also nicht mit einer schnellen Lösung rechnen :)

5voto

Phill Pafford Punkte 80621

Ich glaube, dies ist als ein PHP-Fehler

Der Debug-Backtrace zeigt Dateiname und Zeilennummer des aufrufenden Skripts. Für den Fall, dass Funktion von innen aufgerufen wird internen Funktion aufgerufen wird (eventuell als Callback) können kein Dateiname und kein Lineno gesetzt werden.

2voto

Ya Youbetcha Punkte 81

Unabhängig von jedem "Bug", "Feature" oder was auch immer die Leute, die PHP pflegen, sagen möchten, funktioniert debug_backtrace() nicht so, wie ich es erwarten würde.

Hier ist meine Lösung (sie ist hässlich, aber für mich funktioniert sie):

function dbg($msg="")
{
    ob_start();
    debug_print_backtrace(0,1);
    $_ = ob_get_clean();
    list($ignore,$line_number) = explode(':', $_);
    $line_number += 0;

    $backtrace = debug_backtrace(0);
    extract($backtrace[1]);
    echo "<pre>$class::$function($msg) : $line_number</pre>";
}

Die PHP-Funktion debug_print_backtrace(0,1); ergibt etwa Folgendes:

0 dbg->ping(290) aufgerufen bei[/path/to/filename.php:290]

Da es nur den Trace echot, muss ich ob_get_clean() es als eine Zeichenfolge. Dann parse ich ihn.

In meiner Implementierung möchte ich nur die Klasse, die Funktion, die Zeilennummer und optional eine String-Meldung der aufrufenden Funktion wissen. debug_backtrace() liefert Klasse und Funktion korrekt, aber nicht die Zeilennummer. Deshalb muss ich die Zeilennummer von der Funktion debug_print_backtrace() erhalten.

Für Bonuspunkte.... wie kommt es, dass die Funktion debug_print_backtrace() die Zeilennummer "kennt", aber debug_backtrace() [gelegentlich] nicht, oder??? ... es ist ein Rätsel...

1voto

FGM Punkte 2760

Nachdem ich eine Reihe von ähnlichen Problemen auf bugs.php.net bei verschiedenen PHP-Versionen überprüft habe, scheint dieses Problem bei PHP 7.0 und später, einschließlich 8.0, behoben worden zu sein, die immer eine "Datei" bereitstellen, auch wenn es eine Fälschung wie "Standard Input Code" für Code ist, der von stdin ausgewertet wird.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X