2011-01-03 10 views
12

Me parece que a veces debug_backtrace() no incluye el número de línea de una llamada. ¿Hay alguna razón para esto y alguna forma de corregirlo?¿Por qué es que debug_backtrace() no incluye el número de línea a veces?

Gracias de antemano.

P.S. Y sí, las llamadas que omite los números de línea son mi propio código, no el código PHP interno.

+4

Interesante. Puede publicar un ejemplo? – deceze

+1

¿Está quizás dentro de una excepción, cierre, código evacuado, función tick, manejador de errores (básicamente, cualquier código que opera fuera de la pila de ejecución normal)? Aparte de eso, no puedo ver por qué no obtendrías los números de línea (sin un ejemplo al menos) ... – ircmaxell

+0

@deceze - El código es demasiado complejo para poner un ejemplo. Ojalá pudiera hacerlo, pero tomaría horas o más para identificar algo lo suficientemente simple como para publicar y no es un gran problema para mí pasar todo ese tiempo. – MikeSchinkel

Respuesta

4

creo que esto aparece como una traza inversa PHP Bug

La depuración muestra nombre de archivo y lineno de llamar a la escritura. En el caso de que se llame a la función desde el interior de la función interna (puede ser como una devolución de llamada) no se puede establecer ningún nombre de archivo y lineno.

+0

Gracias por rastrear ese enlace. No creo que una función interna llame al código, pero lo verificaré. – MikeSchinkel

9

Considere siguiente código:

<? 
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)'); 

La ejecución del ejemplo anterior genera siguiente resultado:

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 

El primer elemento traza (índice 0) dice indirectamente (a través de los line y file artículos) que se llamó al método getTheItem desde el método __call.

El segundo elemento traza (índice 1) dice que el método __call fue llamado desde algún lugar (falta line y file artículos).

El tercer elemento de seguimiento (índice 2) dice que se llamó al método test desde el alcance global del script.

El lugar de la llamada al método __call es probablemente en algún código de resolución de método en algún lugar del código del intérprete php. Hay dos posibilidades de arreglarlo. O el segundo elemento debe referir el archivo de código fuente y la línea del intérprete o el segundo y el tercer elemento de rastreo deben fusionarse en uno. Yo personalmente preferiría la segunda solución ya que las partes internas del intérprete no son interesantes para mí (así es como parecen hacerlo en el rastreo de Python), sin embargo, entiendo que a veces la primera solución proporciona un rastro más explícito (especialmente cuando es una devolución de llamada que es llamado desde el interior).

Por lo tanto, parece que el desarrollador (es) responsable (o al menos mantener) el código de la función debug_backtrace no lo percibe como un error o tal vez no tiene una manera fácil de solucionarlo. Sería correcto rellenar los artículos line y file con algunos valores de marcador de posición (por ejemplo, <unknown-file> y 0 o incluso nulos) y enfatizarlo en la documentación. A menos que alguien los convenza con éxito de hacerlo, solo tiene que manejar el caso especial en su código.

Escribí anteriormente solo para compartir mi comprensión del comportamiento extraño de la función.Si alguien tiene la voluntad de luchar por un mundo un poco mejor, aquí están los enlaces a algunos informes de errores relacionados:

El informe más antiguo es de 2003, por lo que no debería cuenta con una solución rápida :)

+0

Muchas gracias por la respuesta detallada. ¡Excelente trabajo! – MikeSchinkel

1

Independientemente de cualquier "error", "función", lo que digan las personas que mantienen PHP, el debug_backtrace() no funciona como era de esperar.

Aquí está mi solución (es feo, pero funciona para mí):

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

La función de PHP debug_print_backtrace (0,1); producirá algo como esto:

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

Ya que sólo la traza ecos, tengo que ob_get_clean() como una cuerda. Luego lo analizo.

En mi implementación, solo quiero saber la clase, la función, el número de línea y, opcionalmente, un mensaje de cadena desde la función de llamada. debug_backtrace() proporciona clase y función correctamente, pero no número de línea. Es por eso que tengo que obtener el número de línea de la función debug_print_backtrace().

Para puntos de bonificación ... ¿cómo es que la función debug_print_backtrace() "conoce" el número de línea, pero debug_backtrace() [ocasionalmente] no, eh ??? ... es un misterio ...

Cuestiones relacionadas