2011-01-03 24 views
12

Ich finde, dass manchmal debug_backtrace() die Leitungsnummer für einen Anruf nicht enthält. Gibt es einen Grund, warum dies so ist und wie man es korrigieren kann?Warum enthält debug_backtrace() Zeilennummer manchmal nicht?

Vielen Dank im Voraus.

P.S. Und ja, die Anrufe, für die Zeilennummern weggelassen werden, sind mein eigener Code, kein interner PHP-Code.

+4

Interessant. Können Sie ein Beispiel veröffentlichen? – deceze

+1

Ist es vielleicht innerhalb einer Ausnahme, Schließung, evaled Code, Tick-Funktion, Fehler-Handler, (im Grunde jeder Code, der von der normalen Ausführung Stack funktioniert)? Ansonsten kann ich nicht sehen, warum Sie keine Zeilennummern erhalten würden (ohne ein Beispiel) ... – ircmaxell

+0

@deceze - Der Code ist viel zu komplex, um ein Beispiel zu veröffentlichen. Ich wünschte, ich könnte es, aber es würde wahrscheinlich Stunden oder länger dauern, um etwas zu finden, das einfach genug ist, um es zu veröffentlichen, und es ist nicht so ein großes Problem für mich, die ganze Zeit zu verbringen. – MikeSchinkel

Antwort

4

Ich denke, das als PHP Bug aufgeführt wird

Die Debug-Backtrace zeigt Dateinamen und lineno Skript aufrufen. Im Fall Funktion wird von innen interne Funktion aufgerufen (kann als Rückruf sein) kein Dateiname und Lineno kann festgelegt werden.

+0

Vielen Dank, dass Sie diesen Link gefunden haben. Ich glaube nicht, dass Code von einer internen Funktion aufgerufen wird, aber ich werde es überprüfen. – MikeSchinkel

9

folgenden Code Betrachten:

<? 
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 Beispiel 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 

Der erste Backtrace Element (Index 0) sagt indirekt (durch die line und file Artikel) dass die getTheItem Methode von der __call Methode aufgerufen wurde.

Der zweite Backtrace Artikel (Index 1) sagt, dass die __call Methode von irgendwo genannt wurde (fehlende line und file Artikel).

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

Die Stelle der __call Methodenaufruf ist wahrscheinlich in einer Methode Auflösung Code irgendwo im PHP-Interpreter-Code. Es gibt zwei Möglichkeiten, es zu beheben. Entweder sollte das zweite Element die Quellcodedatei und die Zeile des Interpreters verweisen, oder das zweite und das dritte Backtrace-Element sollten zu einem zusammengeführt werden. Ich persönlich würde die zweite Lösung bevorzugen, da die Interna des Interpreters für mich nicht interessant sind (so scheinen sie es in Pythons Traceback zu tun), aber ich verstehe, dass manchmal die erste Lösung eine explizitere Spur liefert (besonders wenn es ein Callback ist) aus dem Inneren aufgerufen).

So oder so, es scheint, dass die Entwickler, die für den Code der debug_backtrace-Funktion verantwortlich sind (oder zumindest beibehalten), es nicht als einen Fehler wahrnehmen oder vielleicht keine einfache Möglichkeit, es zu beheben. Es wäre in Ordnung, die line und file Elemente mit einigen Platzhalterwerten (z. B. <unknown-file> und 0 oder sogar Null) zu füllen und es in der Dokumentation zu betonen. Wenn nicht jemand sie erfolgreich dazu überreden kann, müssen Sie nur den Sonderfall in Ihrem Code behandeln.

Ich schrieb oben, nur um mein Verständnis des seltsamen Verhaltens der Funktion zu teilen.Wenn jemand eine Bereitschaft für eine etwas bessere Welt zu kämpfen hat, sind hier einige Links zu verwandten Fehlerberichte:

Der älteste Bericht stammt aus dem Jahr 2003, also sollten Sie nicht zählen Sie auf eine schnelle Lösung :)

+0

Vielen Dank für die ausführliche Antwort. Ausgezeichnete Arbeit! – MikeSchinkel

1

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

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

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); so etwas wie dieses produzieren:

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

Da es nur echos die Spur, muss ich ob_get_clean() es als eine Schnur. Dann analysiere ich es.

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

Für Bonuspunkte .... Wie "weiß" die Funktion debug_print_backtrace() die Zeilennummer, aber debug_backtrace() [gelegentlich] nicht, wie ??? ... es ist ein Geheimnis ...

Verwandte Themen