2011-01-03 36 views
12

Tôi thấy rằng đôi khi debug_backtrace() không bao gồm số dòng cho cuộc gọi. Có một số lý do tại sao điều này là và bất kỳ cách nào để sửa chữa nó?Tại sao debug_backtrace() không bao gồm số dòng đôi khi?

Xin cảm ơn trước.

P.S. Và có, các cuộc gọi mà nó bỏ qua số dòng là mã của riêng tôi, không phải mã PHP nội bộ.

+4

Thú vị. Bạn có thể đăng một ví dụ? – deceze

+1

Có lẽ nó nằm trong một ngoại lệ, đóng, đánh giá mã, hàm đánh dấu, trình xử lý lỗi, (về cơ bản là bất kỳ mã nào hoạt động ngoài ngăn xếp thực thi bình thường)? Khác hơn thế, tôi không thể hiểu tại sao bạn sẽ không nhận được số dòng (không có ít nhất một ví dụ) ... – ircmaxell

+0

@deceze - Mã quá phức tạp để đăng một ví dụ. Tôi ước gì có thể nhưng có thể mất hàng giờ hoặc lâu hơn để xác định một thứ gì đó đủ đơn giản để đăng và nó không phải là vấn đề lớn đối với tôi để dành tất cả thời gian đó. – MikeSchinkel

Trả lời

4

Tôi nghĩ rằng đây là liệt kê như là một vết lùi PHP Bug

Các debug thấy tên tập tin và lineno gọi kịch bản. Trong trường hợp chức năng được gọi từ bên trong chức năng nội bộ (có thể gọi là gọi lại) không thể đặt tên tệp và lineno.

+0

Cảm ơn bạn đã theo dõi liên kết đó. Tôi không nghĩ rằng mã đang được gọi bởi một chức năng nội bộ nhưng tôi sẽ kiểm tra. – MikeSchinkel

9

Hãy xem xét đoạn mã sau:

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

Việc thực hiện ví dụ trên tạo ra sau đầu ra:

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 

Mục backtrace đầu tiên (chỉ số 0) nói gián tiếp (thông qua linefile mục) phương thức getTheItem được gọi từ phương thức __call.

Mục backtrace thứ hai (chỉ số 1) nói rằng phương pháp __call được gọi từ đâu đó (thiếu linefile bài).

Mục backtrace thứ ba (chỉ số 2) cho biết phương thức test được gọi từ phạm vi toàn cục của tập lệnh.

Địa điểm của cuộc gọi phương thức __call có thể là ở một số mã phân giải phương thức nào đó trong mã thông dịch php. Có hai khả năng sửa chữa nó. Mục thứ hai nên tham chiếu đến tệp và mã nguồn của trình thông dịch hoặc mục thứ hai và thứ ba của các mục backtrace sẽ được hợp nhất thành một. Cá nhân tôi thích giải pháp thứ hai vì nội bộ của thông dịch viên không thú vị với tôi (đây là cách họ làm trong traceback của python), tuy nhiên tôi hiểu rằng đôi khi giải pháp đầu tiên cung cấp dấu vết rõ ràng hơn (đặc biệt là khi gọi lại được gọi từ nội bộ). Vì vậy, có vẻ như (các) nhà phát triển chịu trách nhiệm (hoặc ít nhất là duy trì) mã của hàm debug_backtrace không nhận thấy nó là lỗi hoặc có thể không có cách nào dễ dàng để sửa lỗi. Bạn có thể điền các mặt hàng linefile với một số giá trị giữ chỗ (ví dụ: <unknown-file>0 hoặc thậm chí nulls) và nhấn mạnh nó trong tài liệu. Trừ khi ai đó thuyết phục họ làm điều đó, bạn chỉ cần xử lý trường hợp đặc biệt trong mã của bạn.

Tôi đã viết ở trên chỉ để chia sẻ sự hiểu biết của tôi về hành vi kỳ lạ của hàm.Nếu ai đó có một sự sẵn sàng để đấu tranh cho một thế giới tốt hơn một chút, đây là một liên kết đến một số báo cáo lỗi liên quan:

Báo cáo lâu đời nhất là từ năm 2003, vì vậy bạn không nên đếm trên một sửa chữa nhanh :)

+0

Cảm ơn bạn rất nhiều vì câu trả lời chi tiết. Tuyệt vời! – MikeSchinkel

1

Bất kể "lỗi", "tính năng", bất kể những người duy trì PHP muốn nói, debug_backtrace() không hoạt động như tôi mong đợi.

Đây là giải pháp của tôi (nó là xấu xí, nhưng nó làm việc cho tôi):

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

Chức năng PHP debug_print_backtrace (0,1); sẽ tạo ra một cái gì đó như thế này:

# 0 dbg-> ping (290) gọi tại [/path/to/filename.php:290]

Vì nó chỉ echos các dấu vết, tôi phải ob_get_clean() nó như một chuỗi. Sau đó tôi phân tích nó.

Trong quá trình triển khai, tôi chỉ muốn biết lớp, chức năng, số dòng và tùy chọn, một thông báo chuỗi từ chức năng gọi. debug_backtrace() cung cấp lớp và hàm đúng, nhưng không cung cấp số dòng. Đó là lý do tại sao tôi phải lấy số dòng từ hàm debug_print_backtrace().

Đối với điểm thưởng .... làm thế nào mà hàm debug_print_backtrace() "biết" số dòng, nhưng debug_backtrace() [thỉnh thoảng] không, eh ??? ... đó là một bí ẩn ...

Các vấn đề liên quan