Cách tìm nguyên nhân lỗi phân đoạn trong C++

Cach Tim Nguyen Nhan Loi Phan Doan Trong C



Lỗi phân đoạn, còn được gọi là lỗi phân đoạn, là một loại lỗi xảy ra khi một chương trình cố gắng truy cập vào phần bộ nhớ mà nó không được phép truy cập. Khi xảy ra lỗi phân đoạn, hệ điều hành sẽ chấm dứt chương trình để ngăn nó gây ra các sự cố khác. Lỗi này thường biểu thị một lỗi hoặc lỗi lập trình trong mã của chương trình, chẳng hạn như truy cập một con trỏ chưa được khởi tạo, hủy tham chiếu một con trỏ rỗng hoặc vượt quá giới hạn của một mảng.

Lỗi phân đoạn có thể khó gỡ lỗi vì chúng thường dẫn đến sự cố mà không cung cấp thông báo lỗi chi tiết. Tuy nhiên, các công cụ như GDB (GNU Debugger) có thể giúp xác định nguồn gốc của lỗi phân đoạn bằng cách kiểm tra trạng thái của chương trình và dấu vết ngăn xếp tại thời điểm xảy ra lỗi.

Điều quan trọng cần lưu ý là lỗi phân đoạn thường do lỗi lập trình gây ra và được coi là lỗi. Chúng cần được khắc phục bằng cách xem xét và sửa mã có vấn đề. Nguyên nhân phổ biến của lỗi phân đoạn bao gồm:







  • Hủy tham chiếu các con trỏ null hoặc chưa được khởi tạo
  • Viết hoặc đọc ngoài giới hạn của một mảng
  • Sử dụng bộ nhớ đã được giải phóng hoặc giải phóng trước đó
  • Tràn ngăn xếp hoặc ngăn xếp bị hỏng
  • Sử dụng các biến chưa được khởi tạo

Bằng cách kiểm tra cẩn thận mã của bạn và sử dụng các công cụ gỡ lỗi như GDB, bạn có thể xác định và sửa các lỗi phân đoạn, đảm bảo rằng chương trình của bạn hoạt động chính xác và không gặp phải những lỗi này.



Trình gỡ lỗi GDB

GDB (GNU Debugger) là một công cụ gỡ lỗi mạnh mẽ giúp xác định và phân tích các vấn đề trong các chương trình được biên dịch, bao gồm cả lỗi phân đoạn. Nó cho phép bạn kiểm tra trạng thái của chương trình, kích hoạt các điểm dừng và quan sát luồng thực thi.



Để sử dụng GDB một cách hiệu quả nhằm gỡ lỗi các lỗi phân đoạn, bạn cần biên dịch chương trình C++ của mình với các biểu tượng gỡ lỗi được bật. Các ký hiệu này bao gồm thông tin bổ sung về cấu trúc, biến và chức năng của chương trình hỗ trợ quá trình gỡ lỗi.





Tìm lỗi phân đoạn trong C++ với GDB

Dưới đây là đoạn mã ví dụ gây ra lỗi phân đoạn:

#include

int chủ yếu ( ) {

int * ptr = nullptr ;

* ptr = 5 ;

trở lại 0 ;

}

Trước tiên hãy giải thích mã. Sau đó, chúng ta sẽ thảo luận theo các bước về cách tìm lỗi phân đoạn trong mã trước đó.



Lệnh tiền xử lý “#include ” thêm tệp tiêu đề cần thiết để cung cấp các đặc điểm luồng đầu vào cũng như đầu ra trong C++.

Bên trong hàm main(), có một khai báo một biến con trỏ “ptr” kiểu int*. Giá trị “nullptr” được sử dụng làm giá trị khởi tạo của con trỏ, là một giá trị con trỏ null đặc biệt cho biết rằng nó không trỏ đến bất kỳ vị trí bộ nhớ hợp lệ.

Việc thử hủy tham chiếu được thực hiện bằng con trỏ null “ptr” trong dòng tiếp theo là “*ptr = 5;”. Trong trường hợp này, vì “ptr” được đặt thành “nullptr”, nên không có vị trí bộ nhớ hợp lệ nào để truy cập.

Bây giờ, chúng ta sẽ thảo luận về một số bước cần áp dụng để biên dịch chương trình nhằm tìm ra lỗi phân đoạn.

Bước 1: Kích hoạt biểu tượng gỡ lỗi

Để bắt đầu, hãy đảm bảo biên dịch chương trình C++ của bạn với các ký hiệu gỡ lỗi được bật. Để cung cấp thông tin gỡ lỗi cho tệp thực thi trong quá trình biên dịch, hãy sử dụng cờ “-g”. Hãy xem xét trường hợp chúng ta có một tệp C++ có tên là “main.cpp”.

$ g++ -g chính.cpp -O chủ yếu

Bước 2: Chạy GDB

Sau khi chương trình được biên dịch với các ký hiệu gỡ lỗi, hãy chạy GDB bằng cách chuyển tệp thi hành làm đối số.

$ gdb chủ yếu

Bước 3: Bắt đầu chương trình

Bắt đầu chương trình bằng cách gõ “run” hoặc “r” tại dấu nhắc GDB:

$ ( gdb ) chạy

Chương trình của bạn sau đó sẽ bắt đầu thực hiện.

Bước 4: Xác định lỗi phân đoạn

Chương trình tiếp tục chạy cho đến khi gặp lỗi phân đoạn. Sau đó, chương trình ngừng chạy và GDB tạo ra thông báo lỗi.

Ví dụ: hãy xem xét đoạn mã đã được giải thích trước đó khi chúng ta cố gắng gán giá trị 5 cho vị trí bộ nhớ được trỏ bởi con trỏ null, nó sẽ dẫn đến lỗi phân đoạn. Chương trình ngay lập tức kết thúc tại dòng xảy ra lỗi phân đoạn.

Khi chạy chương trình này với GDB, bạn sẽ thấy kết quả đầu ra tương tự như sau:

Đầu ra này cho biết đã xảy ra lỗi phân đoạn trong chức năng chính ở dòng 5 của tệp “main.cpp”.

Bước 5: Kiểm tra dấu vết ngăn xếp

Để hiểu rõ hơn về lỗi phân đoạn, bạn có thể kiểm tra dấu vết ngăn xếp bằng lệnh “backtrace” hoặc đơn giản là “bt”. Lệnh này hiển thị chuỗi các lệnh gọi hàm dẫn đến sự cố.

$ ( gdb ) bt

Dấu vết ngăn xếp được hiển thị cho biết các hàm được gọi trước lỗi phân đoạn:

Đầu ra này cho chúng ta biết rằng lỗi phân đoạn đã xảy ra trong hàm chính ở dòng 5 của tệp “main.cpp”.

Bước 6: Đặt điểm dừng

Để điều tra thêm, bạn có thể đặt điểm dừng ở các dòng mã cụ thể để tạm dừng việc thực thi chương trình tại các điểm đó. Điều này cho phép bạn kiểm tra trạng thái và các biến của chương trình. Ví dụ: để đặt điểm dừng ở dòng 5 của “main.cpp”, hãy sử dụng lệnh “break” như sau:

$ ( gdb ) phá vỡ chính.cpp: 5

Điều này đặt điểm ngắt ở dòng 5 của tệp “main.cpp”:

Bước 7: Tiếp tục thực thi

Sau khi thiết lập các điểm ngắt, hãy tiếp tục thực hiện chương trình bằng lệnh “tiếp tục” hoặc đơn giản là “c”:

$ ( gdb ) Tiếp tục

Chương trình tiếp tục chạy cho đến khi đạt tới breakpoint.

Bước 8: Kiểm tra các biến và mã

Khi chương trình dừng ở điểm dừng, bạn có thể sử dụng các lệnh GDB khác nhau để kiểm tra các biến, duyệt qua mã và điều tra nguyên nhân gây ra lỗi phân đoạn.

Bước 9: Thoát GDB

Sau khi hoàn tất việc gỡ lỗi, bạn có thể thoát GDB bằng lệnh “thoát”:

$ ( gdb ) từ bỏ

Điều này cung cấp cái nhìn tổng quan cơ bản về cách sử dụng GDB để tìm các lỗi phân đoạn trong chương trình C++. GDB cung cấp nhiều tính năng và lệnh khác có thể giúp gỡ lỗi và bạn có thể tham khảo tài liệu GDB để biết thông tin chuyên sâu hơn.

Phần kết luận

Bài viết này trình bày cách sử dụng GDB để tìm lỗi phân đoạn trong C++. Chúng tôi đã giải thích cho bạn các bước cần phải tuân theo. Các bước này cung cấp giải thích toàn diện về cách tìm lỗi phân đoạn trong C++ bằng GDB. Bằng cách làm theo các bước này và sử dụng các tính năng của GDB, bạn có thể xác định và gỡ lỗi một cách hiệu quả nguồn gốc của lỗi phân đoạn trong chương trình C++ của mình.