Brian Kernighan đã có câu nói nổi tiếng, “Mọi người đều biết rằng việc gỡ lỗi khó gấp đôi so với việc viết một chương trình ngay từ đầu. Vì vậy, nếu bạn thông minh hết mức có thể khi bạn viết nó, thì bạn sẽ làm thế nào để gỡ lỗi cho nó? ”. Đối với tôi, điều này không chỉ có nghĩa là “giữ cho nó đơn giản”. Nó cũng có nghĩa rằng gỡ lỗi là trọng tâm của lập trình – bạn không thể trở thành một lập trình viên giỏi nếu không có khả năng gỡ lỗi tuyệt vời. Hy vọng rằng các mẹo gỡ lỗi C ++ yêu thích của tôi sẽ giúp bạn gỡ lỗi mã thông minh và hiệu quả như bạn đang viết nó ngay từ đầu.
# 1 Bạn cần có bộ công cụ gỡ lỗi C++ đầy đủ
Tất cả những điều khác đều bình đẳng, một nhà phát triển được trang bị tốt hơn sẽ tránh và giải quyết các lỗi nhanh hơn một nhà phát triển được trang bị kém hơn. Dưới đây là 4 loại công cụ gỡ lỗi mà tôi khuyên mọi lập trình viên nên biết cách sử dụng và khi nào. Tôi đã bao gồm các tùy chọn nguồn mở miễn phí và thương mại để bạn khám phá:
Mẹo gỡ lỗi CLion từ Anastasia: phần mềm CLion JetBrains không chỉ cho phép bạn gỡ lỗi mã của mình với phần phụ trợ GDB hoặc LLDB. Nó cũng hỗ trợ với các công cụ khác, bao gồm tích hợp Valgrind và Sanitizers, cũng như các tùy chọn khác nhau để phân tích mã tĩnh.
# 2 Điểm ngắt có điều kiện
Điểm ngắt cho phép bạn dừng việc thực thi chương trình tại một dòng hoặc hàm cụ thể trong mã của bạn. Khi chương trình của bạn chạm điểm ngắt, chương trình sẽ đợi hướng dẫn từ bạn để kiểm tra hoặc thao tác trạng thái ứng dụng, tiếp tục thực thi, v.v.
Để giúp gỡ lỗi C++ hiệu quả hơn, tôi thích sử dụng các điểm ngắt có điều kiện. Thay vì tạm dừng mỗi khi đạt đến điểm ngắt (điều này có thể tẻ nhạt nếu điểm ngắt được xác định trong vòng lặp), tôi có thể xác định điều kiện cho điểm ngắt dừng thực hiện nếu được đáp ứng. Ví dụ: nếu biến “i” thường bằng 0, có thể tôi muốn ngắt nếu “i” không bằng 0:
(gdb) break my_func if i! = 0
Bạn có thể viết khá nhiều điều kiện bạn muốn bằng ngôn ngữ lập trình của chương trình mà bạn debugging, điều này làm cho các điểm ngắt có điều kiện trở nên rất mạnh mẽ và hiệu quả. Điều kiện có thể bao gồm một lệnh gọi hàm, giá trị của một biến hoặc kết quả của bất kỳ biểu thức GDB nào.
Để tìm hiểu thêm, hãy xem hướng dẫn bằng video này, trong đó tôi giải thích về các loại điểm ngắt có điều kiện và nhiều loại điểm ngắt khác cũng như cách sử dụng mỗi loại trong số chúng trong gỡ lỗi của bạn.
Mẹo CLion Debugger từ Anastasia: Trong CLion, bạn có thể dễ dàng chỉ định một điều kiện được kiểm tra mỗi khi một điểm ngắt được nhấn.
# 3 Điểm theo dõi
Giống như các điểm ngắt, một điểm giám sát dừng thực thi, nhưng làm như vậy bất cứ khi nào giá trị của một biểu thức thay đổi, mà không cần phải dự đoán một dòng mã cụ thể nơi điều này có thể xảy ra. Các điểm giám sát cực kỳ hữu ích khi gỡ lỗi các vấn đề đồng thời, chẳng hạn như khi cố gắng hiểu luồng hoặc quy trình nào đang thay đổi tài nguyên được chia sẻ. Biểu thức có thể đơn giản như giá trị của một biến hoặc phức tạp như nhiều biến được kết hợp bởi các toán tử. Những ví dụ bao gồm:
- Tham chiếu đến giá trị của một biến duy nhất.
- Một địa chỉ được truyền đến một kiểu dữ liệu thích hợp. Ví dụ, * (int *) 0x12345678 sẽ xem một vùng 4 byte tại địa chỉ được chỉ định (giả sử một int chiếm 4 byte).
- Một biểu thức phức tạp tùy ý, chẳng hạn như a * b + c / d. Biểu thức có thể sử dụng bất kỳ toán tử nào hợp lệ trong ngôn ngữ mẹ đẻ của chương trình (xem Ngôn ngữ).
# 4 Các lệnh gỡ lỗi C++ do người dùng xác định trong Python
Tôi khuyên bạn nên điều chỉnh trình gỡ lỗi của mình để phù hợp với dự án và nhóm của bạn. Trong GDB, điều này có thể được thực hiện bằng cách tạo các lệnh do người dùng xác định bằng Python. Bạn có thể làm tất cả những điều thông minh để giúp việc phát hiện (và giải quyết) những lỗi khó hiểu một cách dễ dàng. Ngoài ra, có rất nhiều thủ thuật khác mà bạn có thể thực hiện để tùy chỉnh GDB theo nhu cầu gỡ lỗi và dự án cụ thể của mình.
Không tận dụng được Python là điều bạn có thể hối tiếc sau này – một cơ hội bị bỏ lỡ để tăng tốc độ gỡ lỗi C++ của bạn, chưa kể đến chất lượng cuộc sống chung của bạn! Đó là một khoản đầu tư nhỏ trong thời gian sẽ hoàn vốn nhanh chóng và theo thời gian, đáng kể.
Ví dụ: bạn có thể tự động hóa một tác vụ như kiểm tra đầu ra của trình gỡ lỗi thành điều khiển nguồn và chia sẻ nó với đồng đội của bạn. Trong bài đăng trên blog này, tôi chỉ ra cách tích hợp Python với GDB có thể được sử dụng để thực hiện chính xác điều đó.
Mẹo gỡ lỗi CLion từ Anastasia: Bạn có biết rằng trong một phiên gỡ lỗi, bạn có thể truy cập bảng điều khiển GDB / LLDB trực tiếp từ CLion không? Tab này hiển thị luồng đầu ra / lỗi của trình gỡ lỗi và cho phép bạn chạy các lệnh GDB / LLDB.
Trong phiên gỡ lỗi, bạn có thể truy cập bảng điều khiển GDB / LLDB trực tiếp từ CLion: trong cửa sổ Debug tool, mở tab Debugger, sau đó mở tab được đánh dấu . Tab này hiển thị luồng đầu ra / lỗi của trình gỡ lỗi và cho phép bạn chạy các lệnh GDB / LLDB.
Những short cut hữu ích cho bạn:
Ctrl+Shift+F10: Chuyển nhanh sang bảng điều khiển trình gỡ lỗi (chỉ khả dụng trong phiên gỡ lỗi). Trong trường hợp cửa sổ công cụ Gỡ lỗi bị ẩn, hành động này sẽ mở nó và tập trung vào tab bảng điều khiển trình gỡ lỗi.
Ctrl+Space or Tab: Mời hoàn thành lệnh do GDB hoặc LLDB cung cấp.
# 5 Cấu trúc pretty-printer
Việc in các biến, cấu trúc và lớp là một phần quan trọng của việc gỡ lỗi. Theo mặc định, trình gỡ lỗi có thể không in giá trị theo cách giúp nhà phát triển dễ hiểu.
Ví dụ: khi tôi in cấu trúc siginfo_t, lệnh print trả về tất cả dữ liệu trong cấu trúc, bao gồm cả việc mở rộng các liên kết mà nó sử dụng:
Lộn xộn và không dễ đọc!
May mắn thay, GDB có thể được mở rộng với các chức năng “pretty-printer”. Khi GDB in một giá trị, nó sẽ kiểm tra xem có pretty-printers nào đã đăng ký cho giá trị đó hay không. Nếu vậy, GDB sử dụng nó để hiển thị giá trị. Nếu không, giá trị sẽ in theo cách thông thường.
Phải mất một chút mã hóa trước để tạo ra chức năng pretty-printers, nhưng tôi hứa rằng nó sẽ giúp bạn tiết kiệm rất nhiều thời gian nhìn chằm chằm vào màn hình máy tính của mình.
Mẹo gỡ lỗi CLion từ Anastasia: Nếu bạn thêm pretty-printers tùy chỉnh vào GDB, CLion sẽ sử dụng chúng theo mặc định.
# 6 Time Travel Debugging
Thông thường, bạn cần biết những gì chương trình của bạn thực sự đã làm, trái ngược với những gì bạn mong đợi nó sẽ làm. Đây là lý do tại sao gỡ lỗi C++ thường liên quan đến việc tái tạo lỗi nhiều lần, từ từ đưa ra ngày càng nhiều thông tin cho đến khi bạn ghim nó xuống.
Gỡ lỗi Time Travel loại bỏ tất cả những phỏng đoán và thử và sai – trình gỡ lỗi có thể cho bạn biết trực tiếp điều gì vừa xảy ra.
Các trình gỡ lỗi miễn phí như GDB có khả năng Gỡ lỗi Time Travel được tích hợp sẵn. Nó hoạt động khá tốt, nhưng bạn phải sẵn sàng hy sinh hiệu suất (rất nhiều). Trình gỡ lỗi Time Travel được xây dựng có mục đích thương mại như UDB cung cấp hiệu suất Gỡ lỗi Time Travel nhanh hơn nhiều.
Quá trình này giống như gỡ lỗi thông thường ngoại trừ việc bạn có thể bước / tiếp tục quay ngược thời gian. Các điểm ngắt và điểm theo dõi hoạt động ngược lại, chẳng hạn như có thể giúp bạn tiếp tục trực tiếp đến điểm trước đó trong chương trình mà tại đó một biến cụ thể thay đổi. Các điểm quan sát ngược có thể cực kỳ mạnh mẽ. Tôi biết một số trường hợp lỗi đã lẩn tránh một nhà phát triển trong nhiều tháng hoặc thậm chí nhiều năm đã được giải quyết trong vài giờ với sức mạnh của các điểm giám sát ngược.
Trong video này, tôi chứng minh gỡ lỗi ngược trong GDB. Kiểm tra nó: nó chỉ cho bạn từng bước (ngược lại) cách tìm ra lỗi trong chương trình của tôi.
# 7 Lệnh find để tìm kiếm một chuỗi byte
Đôi khi khi gỡ lỗi, bạn cần tìm một chuỗi byte cụ thể trong không gian bộ nhớ của chương trình. Có lẽ bạn muốn xem tất cả các con trỏ đến một đối tượng cụ thể. Vì vậy, cứ tám byte trong bộ nhớ tương ứng với chuỗi byte là một địa chỉ bạn muốn xác định.
Lệnh find trong GDB cung cấp cho bạn một kiểu kiểm tra khác đối với chương trình của bạn. Tất cả các giá trị tìm kiếm.
Tác giả: Greg (@gregthelaw) là người đồng sáng lập và Giám đốc điều hành tại Undo. Anh ấy thực tâm là một lập trình viên, nhưng thích giữ một chân trong thế giới phần mềm và một chân trong thế giới kinh doanh. Greg thấy đặc biệt bổ ích khi biến công nghệ phần mềm sáng tạo thành sự phát triển kinh doanh thực sự. Greg có hơn 20 năm kinh nghiệm trong cả lĩnh vực học thuật và các công ty phần mềm khởi nghiệp sáng tạo.
Nguồn: blog jetbrains
Dịch: Ann Phạm