Giả sử bạn không có sẵn trình gỡ lỗi, cách tiếp cận hiệu quả đối với mã gỡ lỗi không hoạt động (như mong đợi) là gì?
Giả sử bạn không có sẵn trình gỡ lỗi, cách tiếp cận hiệu quả đối với mã gỡ lỗi không hoạt động (như mong đợi) là gì?
Câu trả lời:
Có một số kỹ thuật:
Ghi nhật ký. Nếu bạn không có quyền truy cập tệp, hãy đăng nhập vào bảng điều khiển nối tiếp hoặc bất kỳ thiết bị đầu ra nào khả dụng. Đó là một ý tưởng tốt để luôn luôn viết mã của bạn khi đăng nhập, cho phép biên dịch có điều kiện cho các cấp ghi nhật ký khác nhau, từ 'không' đến 'quá mức'.
Cắt nó xuống. Loại trừ các phần của mã của bạn xung quanh một lỗi đáng ngờ từng điểm một và phân tích những gì bạn đã làm khi lỗi biến mất.
Khẳng định hoặc hợp đồng. Đó là một ý tưởng tốt để nhồi mã của bạn với các xác nhận ngay từ đầu. Chúng không chỉ giúp gỡ lỗi mà còn đóng vai trò là tài liệu bổ sung cho mã của bạn.
Tương tự như 2. - thay đổi đầu vào của bạn và cải tổ lại mã trừ khi lỗi biến mất hoặc thay đổi hành vi của nó. Thường là một ý tưởng tốt để chơi với các mức tối ưu hóa khác nhau (nếu bạn đang mã hóa bằng C hoặc C ++), vì các lỗi liên quan đến con trỏ có xu hướng cực kỳ dễ bay hơi trong hành vi của chúng.
Phiên bản tự động của 3. - sử dụng mã cụ, ví dụ: chạy nhị phân theo valgrind.
Và tất nhiên còn nhiều công cụ và thủ thuật khác, tùy thuộc vào bản chất của môi trường thực thi và mã của bạn.
Nhận một đồng nghiệp và giải thích vấn đề một cách chi tiết trong khi bạn đi qua các mã rắc rối từng bước.
Thường xuyên hành động giải thích làm rõ cho đồng nghiệp hoặc chính bạn.
Có một hệ thống đăng nhập để quản lý đầu ra chương trình? Có ít nhất một giao diện điều khiển để in hoặc tập tin bạn có thể ghi vào? Sử dụng bảng điều khiển hoặc tệp nhật ký là cách bạn có thể gỡ lỗi mà không cần trình gỡ lỗi. Cung cấp cho chương trình một đầu vào sao cho bạn biết đầu ra sẽ là gì, sau đó xác minh rằng đầu ra hoạt động và đảm bảo việc ghi nhật ký của bạn cung cấp cho bạn nhiều chi tiết của quy trình. Sau đó thử với một đầu vào cung cấp đầu ra sai. hy vọng, các bản ghi sẽ cung cấp cho bạn một dấu vết chi tiết về những gì đã sai.
Phụ thuộc. Nó đã làm việc trước đây? Nếu mã được sử dụng để làm việc đột ngột, thì bạn nên kiểm tra rất kỹ những thay đổi gần đây nhất.
1) Làm bất cứ điều gì bạn cần làm để làm cho lỗi có thể tái tạo 100% hoặc gần 100% nhất có thể
2) Theo dõi sự cố, sử dụng printf () hoặc phương tiện ghi nhật ký khác. Đây là một nghệ thuật, mặc dù, và nó phụ thuộc vào bản chất của lỗi.
Nếu bạn hoàn toàn không biết gì về vị trí của lỗi, nhưng ví dụ bạn biết một điều kiện trở thành sai tại một thời điểm nào đó (trạng thái của chương trình bị hỏng - hãy gọi nó làBroken ()), bạn có thể tìm kiếm chi tiết / tìm kiếm phân vùng để tìm ra vị trí của vấn đề. Ví dụ: ghi lại giá trị của isBroken () ở đầu ở cuối các phương thức chính:
void doSomething (void)
{
printf("START doSomething() : %d\n", isBroken());
doFoo();
doBar();
printf("END doSomething() : %d\n", isBroken());
}
Nếu trong nhật ký bạn thấy
START doSomething() : 0
END doSomething() : 1
bạn biết có gì đó không ổn ở đó Vì vậy, bạn xóa tất cả các mã đăng nhập khác và thử phiên bản mới này:
void doSomething (void)
{
printf("START doSomething() : %d\n", isBroken());
doFoo();
printf("AFTER doFoo() : %d\n", isBroken());
doBar();
printf("END doSomething() : %d\n", isBroken());
}
Bây giờ trong nhật ký bạn có thể thấy điều này
START doSomething() : 0
AFTER doFoo() : 0
END doSomething() : 1
Vì vậy, bây giờ bạn biết doBar () kích hoạt lỗi và bạn có thể lặp lại quy trình trên trong doBar (). Lý tưởng nhất là bạn sẽ thu hẹp lỗi thành một dòng duy nhất.
Tất nhiên điều này có thể giúp bạn tiết lộ các triệu chứng của lỗi chứ không phải nguyên nhân gốc - ví dụ: bạn tìm thấy một con trỏ NULL không nên là NULL, nhưng tại sao? Sau đó, bạn có thể đăng nhập lại, nhưng kiểm tra một điều kiện "bị hỏng" khác.
Nếu bạn gặp sự cố thay vì trạng thái bị hỏng, thì ít nhiều giống nhau - dòng cuối cùng của nhật ký cung cấp cho bạn một gợi ý về nơi mọi thứ bị phá vỡ.
Sau khi các câu trả lời khác không thành công , luôn có gỡ lỗi tìm kiếm nhị phân :
Lưu ý: rõ ràng, kỹ thuật này chỉ hoạt động nếu bạn có thể tái tạo vấn đề một cách đáng tin cậy.
'"Công cụ gỡ lỗi hiệu quả nhất vẫn là suy nghĩ cẩn thận, cùng với các câu lệnh in được đặt một cách thận trọng." - Brian Kernighan 'Trong ngày đó có thể là sự thật! Phương pháp hiệu quả nhất là xem xét các bài kiểm tra đơn vị nhưng tôi đoán là bạn không có bài kiểm tra nào.
Nó phụ thuộc vào lỗi.
Nếu lỗi là loại 'tại sao mã lại làm A', thì có thể hữu ích để kiểm tra sự hiểu biết của bạn về mã xung quanh vị trí của 'mã làm A'. Giới thiệu mã mới mà bạn dự kiến sẽ tạo ra các lỗi mới (mã này sẽ làm cho nó làm B, điều này sẽ làm cho nó làm C). Tôi thường nhanh chóng tìm thấy một số mã mới tạo ra hành vi mà tôi không mong đợi. Sau đó, tôi kiên nhẫn chờ đợi trong khi tâm trí của tôi xây dựng một mô hình tinh thần cập nhật về hành vi mã để thay đổi cuối cùng có ý nghĩa, và sau đó thay đổi mô hình tinh thần đó thường giải thích lý do tại sao mã đang thực hiện A.
Trường hợp thứ hai đã được thảo luận chi tiết ở đây. Trường hợp bạn đã thừa hưởng mã, không có mô hình tinh thần vững chắc về cách mã hoạt động, không có ý tưởng hay về vị trí cụ thể của lỗi, v.v. Trong trường hợp này, hãy truy sâu / phân chia và- phương pháp chinh phục với báo cáo in có thể làm việc. Và nếu nó nằm dưới sự kiểm soát nguồn, hãy đảm bảo kiểm tra thay đổi mã gần đây nhất.
Mở rộng trên "Công cụ gỡ lỗi hiệu quả nhất vẫn là suy nghĩ cẩn thận, cùng với các tuyên bố in được đặt một cách thận trọng."
Đầu tiên, cố gắng thu hẹp thời điểm lỗi xảy ra. Làm cho các triệu chứng người dùng có thể quan sát hệ thống quan sát được. (giả sử, một số chuỗi thay đổi thành vô nghĩa, thêm một vòng lặp thăm dò nội dung của tập lệnh và kích hoạt gỡ lỗi của bạn khi nó thay đổi.) Tất nhiên nếu lỗi là sự cố, hãy thêm xử lý segfault.
Sau đó cố gắng thu hẹp luồng nếu sự cố xảy ra với môi trường đa luồng. Cung cấp cho mỗi luồng một mã định danh và kết xuất nó khi lỗi xảy ra.
Một khi bạn có chủ đề, hãy rắc mã của chủ đề đã cho bằng các bản in một cách cẩn thận để đóng đinh xuống điểm mà nó xuất hiện.
Sau đó quay lại nơi xảy ra hành động thực tế xảy ra (hành động phá hoại thường sẽ khá nhiều trước khi dữ liệu bị hỏng gây ra sự cố.) Kiểm tra cấu trúc / biến nào xảy ra gần đó trong bộ nhớ, quan sát các vòng lặp ảnh hưởng đến chúng, kiểm tra các điểm trong đó giá trị bị hỏng được ghi vào.
Một khi bạn có điểm gây ra sự cố, trước khi sửa nó, hãy suy nghĩ kỹ xem hành vi đúng phải là gì.