2009-08-06 60 views
14

Khi tôi đang gỡ lỗi một cái gì đó mà đi sai trong vòng một, nói trên lặp lại 600, nó có thể là một nỗi đau phải phá vỡ cho mỗi một. Vì vậy, tôi đã cố gắng thiết lập một điểm ngắt có điều kiện, để chỉ phá vỡ nếu tôi = 600. Điều đó hoạt động, nhưng bây giờ phải mất gần một phút để đạt được điểm đó, nơi trước khi nó gần như tức thời. Điều gì đang xảy ra, và có cách nào để sửa chữa nó?Tại sao các điểm ngắt có điều kiện làm chậm chương trình của tôi xuống quá nhiều?

Trả lời

1

Điểm ngắt có điều kiện trong bất kỳ trình gỡ lỗi nào (tôi chỉ phỏng đoán ở đây) yêu cầu quy trình lật qua lại mỗi lần giữa chương trình của bạn và trình gỡ lỗi mỗi khi điểm ngắt được nhấn. Quá trình này tốn thời gian nhưng tôi không nghĩ rằng bạn có thể làm bất cứ điều gì.

22

Khi bạn nhấn điểm ngắt, Windows sẽ dừng quy trình và thông báo cho trình gỡ rối. Nó phải chuyển đổi ngữ cảnh, đánh giá tình trạng, quyết định rằng không, bạn không muốn được thông báo về nó, khởi động lại quá trình và chuyển trở lại. Điều đó có thể mất rất nhiều chu kỳ xử lý. Nếu bạn đang làm nó trong một vòng lặp chặt chẽ, nó sẽ mất một vài đơn đặt hàng của các chu kỳ bộ vi xử lý nhiều hơn một vòng lặp của vòng lặp mất.

Nếu bạn sẵn sàng gây rối với mã của mình một chút, có cách để thực hiện các điểm ngắt có điều kiện mà không phải gánh chịu tất cả chi phí này.

if <condition here> then 
    asm int 3 end; 

Đây là hướng dẫn lắp ráp đơn giản gửi thủ công thông báo điểm dừng tới hệ điều hành. Bây giờ bạn có thể đánh giá tình trạng của bạn bên trong chương trình, mà không cần chuyển đổi ngữ cảnh. Chỉ cần chắc chắn để đưa nó ra một lần nữa khi bạn đang thực hiện với nó. Nếu một int 3 đi vào bên trong một chương trình không được kết nối với một trình gỡ lỗi, nó sẽ tăng một ngoại lệ.

+0

Tôi nghĩ có nhiều lol nhưng bạn đã nói điều đó tốt hơn. –

+0

Mason: tóm tắt tốt; xem ra mặc dù nó rất dễ dàng để lại một số các công trình xây dựng trong mã. Vì vậy, tôi đề nghị rằng nó được thực hiện với một số nhận xét (tôi sử dụng một cái gì đó với @@@) hoặc vĩ mô được đảm bảo không kết thúc trong một sản phẩm thực tế. – Adriaan

+0

Thẻ này được gắn thẻ Delphi, không có macro tiền xử lý hoặc @@@ nhận xét. Một cách đơn giản để đảm bảo rằng bạn không bỏ sót bất kỳ điều gì là grep codebase của bạn cho "int 3" trước khi bạn xây dựng một phiên bản phát hành. –

0

Điểm ngắt trạng thái thông thường hoạt động bằng cách chèn lệnh ngắt phù hợp vào mã và sau đó kiểm tra các điều kiện bạn đã chỉ định. Nó sẽ kiểm tra ở mọi lần lặp lại và nó có thể là cách mà kiểm tra được thực hiện chịu trách nhiệm cho sự chậm trễ vì không có khả năng trình gỡ rối biên dịch và chèn mã kiểm tra và điểm ngắt hoàn toàn vào mã hiện có.

Một cách mà bạn có thể có thể đẩy nhanh điều này là nếu bạn đặt điều kiện theo sau bởi một op không có tác dụng phụ vào mã trực tiếp và phá vỡ op đó. Chỉ cần nhớ để loại bỏ các điều kiện và op khi bạn đang thực hiện.

+0

Nó có lẽ không phải là kiểm tra có điều kiện chính nó, đó là bối cảnh chuyển mạch và chi phí dừng và khởi động lại quá trình. Bạn không nhận thấy rằng với một breakpoint bình thường kể từ khi bạn đất trong debugger anyway, nhưng trên một điều kiện mà nó giữ đi nó trở nên rất rõ ràng rất nhanh chóng. –

6

Nó làm chậm nó xuống bởi vì mỗi khi bạn đạt đến điểm đó, nó phải kiểm tra tình trạng của bạn.

Những gì tôi có xu hướng làm là tạm thời tạo một biến khác như thế này (trong C nhưng phải có thể thực hiện được trong Delphi).

int xyzzynum = 600; 
while (true) { 
    doSomething(); 
    if (--xyzzynum == 0) 
     xyzzynum = xyzzynum; 
} 

thì tôi đặt điểm ngắt không có điều kiện trên dòng "xyzzynum = xyzzynum;".

Chương trình chạy ở tốc độ tối đa cho đến khi nó vượt qua vòng lặp 600 lần, vì trình gỡ lỗi chỉ thực hiện ngắt ngắt bình thường thay vì kiểm tra điều kiện mỗi lần.

Bạn có thể làm cho điều kiện phức tạp như bạn muốn.

+0

+1 Trong trường hợp này op có lẽ có thể sử dụng một cái gì đó đơn giản như nếu tôi = 600 sau đó viết; và đặt điểm ngắt trên mệnh đề ghi. –

+0

+1 cho tham chiếu Hang động khổng lồ. : D –

3

Giải thích của Mason khá tốt.
mã của ông có thể được thực hiện một chút an toàn hơn bằng cách kiểm tra mà bạn chạy dưới debugger:

if (DebugHook <> 0) and <your specific condition here> then 
    asm int 3 end; 

này sẽ không làm bất cứ điều gì khi ứng dụng đang chạy bình thường và sẽ dừng lại nếu nó đang chạy dưới debugger (cho dù được khởi chạy từ IDE hay kèm theo trình gỡ rối).
Và với phím tắt boolean <your specific condition here> thậm chí sẽ không được đánh giá nếu bạn không thuộc trình gỡ lỗi.

+0

Và nó cũng sẽ cung cấp cho [Pascal Warning] Dist.dpr (72): Biểu tượng W1002 'DebugHook' là đặc trưng cho nền tảng - làm cho chúng dễ tìm trước khi đăng ký. –

4

Tiếp tục đến câu trả lời của Mason, bạn có thể làm cho int 3 Assember chỉ được biên dịch tại nếu chương trình được xây dựng với debug có điều kiện định nghĩa:

{$ifdef debug} 
{$message warn 'debug breakpoint present in code'} 
if <condition here> then 
    asm int 3 end; 
{$endif} 

Vì vậy, khi bạn đang gỡ lỗi trong ide, bạn có gỡ lỗi có điều kiện trong các tùy chọn dự án. Khi bạn xây dựng sản phẩm cuối cùng cho khách hàng của mình (với tập lệnh xây dựng?), Bạn sẽ không bao gồm biểu tượng đó, vì vậy nó sẽ không được biên dịch.

Tôi cũng bao gồm chỉ thị trình biên dịch tin nhắn $, vì vậy bạn sẽ thấy cảnh báo khi bạn biên dịch cho bạn biết rằng mã vẫn còn ở đó. Nếu bạn làm điều đó ở mọi nơi bạn sử dụng int 3, sau đó bạn sẽ có một danh sách tốt đẹp của những nơi mà bạn có thể nhấp đúp chuột vào để đưa bạn thẳng đến mã vi phạm.

N @

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