2017-12-31 155 views
6

Chcę użyć register_tick_function(), aby podłączyć następujące połączenia i wydrukować ich ślad stosu z debug_backtrace().PHP debug_backtrace() wywoływana przez register_tick_function() nie zwraca pełnego stosu

Jeśli uruchomię następujący kod.

<?php 

function dump() { 
    // Replace this with var_dump(debug_backtrace()); to print the entire trace. 
    foreach (debug_backtrace() as $trace) 
    echo("Function ${trace['function']}() has been called" . PHP_EOL); 
} 

declare(ticks = 1); 
register_tick_function('dump'); 

print(""); 
array_search('green', Array()); 

Drukuje tylko funkcję dump().

Function dump() has been called 
Function dump() has been called 
Function dump() has been called 

Dlaczego nie widzę print() i array_search() dane śledzenia? Wygląda na to, że stos został zresetowany przed wywołaniem dump(). Jestem też prawie pewien, że działało to prawidłowo w przeszłości.

+2

To było zgłaszane jako błąd kilka lat temu, ale wtedy nie było powtarzalne: https://bugs.php.net/bug.php? id = 70188 –

+0

Testowany. Nie można zreplikować w PHP 7.1 na Win, Ubuntu, docker (ubuntu). Nie można zreplikować w PHP 5.6 na Win, Ubuntu, docker (ubuntu). –

+1

Próbowałem tego na http://phpio.net/s/6v6g, i wydaje się nie działać w żadnej z wersji PHP tam. Zobacz więc: https://stackoverflow.com/questions/7241834/debug-backtrace-from-registered-shutdown-function-inphph. Chociaż ta dotyczy rejestru register_shutdown_function, może być taka sama. Śledzenie może rozpocząć się tylko w miejscu, w którym jest wywoływane, co może nie mieć miejsca w tym przypadku. Jest bardziej podobny do tego: 'print (" ");' 'dump();' 'array_search ('green', Array());' 'dump();' Tak więc w tym przypadku naprawdę jest śledzeniem siebie, ponieważ nie jest ono wywoływane z niczego innego. – Huy

Odpowiedz

1

Nie rozumiesz co to jest ślad, ten stos nie jest listą funkcji, które PHP wykonał zanim dotarł do pewnej linii kodu, ale raczej listą zagnieżdżonych funkcji, które usprawiedliwiają interpreter PHP w konkretnym wierszu kodu .

Pierwszym elementem będzie zawsze ta funkcja, w której aktualnie się znajdujesz, następnym będzie funkcja, która wywołała tę funkcję i tak dalej. Jeśli funkcja zwraca, nie jest już w stosie.

class Foo { 
    public static function bar() { 
     return self::say(); 
    } 

    public static function say() { 
     return debug_backtrace(); 
    } 
} 

var_dump(Foo::say()); 
//[0] => say() 

var_dump(Foo::bar()); 
//[0] => say(); 
//[1] => bar(); 

//Note that this behaviour work the same for require(), include() and eval() 

require_once('test.php'); 

//test.php: 
var_dump(debug_backtrace()); 
//[0] => require_once() 

Gdy PHP interpretuje twój skrypt, porusza się po funkcjach, dodając i usuwając z bieżącego stosu. Stos śledzenia wstecznego nie jest miejscem, w którym logi PHP nazywały funkcje w porządku chronologicznym.

W tym drugim przypadku, jest to rozwiązanie znalazłem: Get a called functions list in PHP