Cho dù bạn có kinh nghiệm như thế nào với tư cách là một lập trình viên, bất kỳ phần mềm nào bạn phát triển cũng không thể hoàn toàn không có lỗi. Đó là lý do tại sao việc xác định lỗi và sửa lỗi là một trong những nhiệm vụ quan trọng nhất trong chu trình phát triển phần mềm. Mặc dù có nhiều cách để tìm lỗi (kiểm tra, tự kiểm tra mã, v.v.), nhưng cũng có phần mềm đặc biệt - được gọi là trình gỡ lỗi - giúp bạn hiểu chính xác vấn đề nằm ở đâu để bạn có thể dễ dàng sửa lỗi.
Giả sử bạn là một lập trình viên C/C++ hoặc phát triển phần mềm bằng ngôn ngữ lập trình Fortran và Modula-2, trong trường hợp này, bạn sẽ vui mừng khi biết rằng có một trình gỡ lỗi tuyệt vời - được gọi là GDB - mà bạn có thể sử dụng để dễ dàng kiểm tra lỗi và các vấn đề khác trong mã của mình. Trong bài viết này, chúng ta sẽ thảo luận về những điều cơ bản của GDB và một số tính năng/tùy chọn hữu ích của nó.
Đầu tiên, để sử dụng thành công các trình gỡ lỗi như GDB, bạn phải biên dịch chương trình của mình để trình biên dịch cũng tạo ra thông tin gỡ lỗi mà trình gỡ lỗi yêu cầu. Ví dụ, trong trường hợp trình biên dịch gcc, mà chúng ta sẽ sử dụng để biên dịch chương trình C ví dụ sau trong hướng dẫn này, bạn cần sử dụng tùy chọn dòng lệnh -g trong khi biên dịch mã của mình.
Để biết trang hướng dẫn sử dụng trình biên dịch gcc nói gì về tùy chọn dòng lệnh này, hãy truy cập tại đây.
Bước tiếp theo là đảm bảo rằng bạn đã cài đặt GDB trên hệ thống của mình. Nếu không phải vậy và bạn đang sử dụng hệ thống dựa trên Debian như Ubuntu, bạn có thể dễ dàng cài đặt công cụ bằng lệnh sau:
Để cài đặt trên bất kỳ bản phân phối nào khác, hãy truy cập tại đây.
Bây giờ, sau khi biên dịch chương trình theo cách sẵn sàng gỡ lỗi và GDB có trên hệ thống của bạn, bạn có thể chạy chương trình ở chế độ gỡ lỗi bằng lệnh sau lệnh:
Mặc dù lệnh này sẽ khởi chạy trình gỡ lỗi GDB, nhưng chương trình thực thi của bạn sẽ không được khởi chạy tại thời điểm này. Đây là thời điểm bạn có thể xác định các thiết lập liên quan đến gỡ lỗi của mình. Ví dụ, bạn có thể định nghĩa điểm dừng yêu cầu GDB tạm dừng thực thi chương trình ở số dòng hoặc hàm cụ thể.
Tiếp theo, để khởi chạy chương trình, bạn sẽ phải thực thi lệnh gdb sau:
Cần đề cập rằng nếu chương trình của bạn yêu cầu truyền một số đối số dòng lệnh, bạn có thể chỉ định chúng tại đây. Ví dụ:
GDB cung cấp nhiều lệnh hữu ích có ích khi gỡ lỗi. Chúng ta sẽ thảo luận một số lệnh trong ví dụ ở phần tiếp theo.
Về cơ bản, mã này thực hiện như sau: nó chọn từng giá trị có trong mảng 'val', gán giá trị đó cho số nguyên 'out', sau đó tính toán 'tot' bằng cách cộng giá trị trước đó của biến và kết quả của '0xffffffff/out.'
Vấn đề ở đây là khi mã được chạy, nó tạo ra kết quả sau lỗi:
Vì vậy, để gỡ lỗi mã, bước đầu tiên là biên dịch chương trình với -g. Đây là lệnh:
Tiếp theo, hãy chạy GDB và cho nó biết tệp thực thi nào chúng ta muốn gỡ lỗi. Đây là lệnh cho việc đó:
Bây giờ, lỗi tôi gặp phải là 'ngoại lệ dấu phẩy động' và như hầu hết các bạn có thể đã biết, lỗi này do n % x gây ra khi x bằng 0. Vì vậy, với suy nghĩ đó, tôi đặt điểm dừng ở dòng số 11, nơi phép chia đang diễn ra. Việc này được thực hiện theo cách sau:
Lưu ý rằng '(gdb)' là dấu nhắc của trình gỡ lỗi. Tôi vừa viết lệnh 'break'.
Bây giờ, tôi yêu cầu GDB bắt đầu thực thi chương trình:
Vì vậy, khi điểm dừng được chạm đến lần đầu tiên, đây là những gì GDB hiển thị trong đầu ra:
Như bạn có thể thấy trong đầu ra ở trên, trình gỡ lỗi đã hiển thị dòng nơi điểm dừng được đặt. Bây giờ, hãy in giá trị hiện tại của 'out.' Bạn có thể thực hiện theo cách sau:
Như bạn thấy, giá trị '5' đã được in ra. Vậy là mọi thứ vẫn ổn vào lúc này. Tôi đã yêu cầu trình gỡ lỗi tiếp tục thực thi chương trình cho đến điểm dừng tiếp theo, điều này có thể thực hiện được bằng lệnh 'c'.
Tôi tiếp tục thực hiện công việc này cho đến khi tôi thấy giá trị của 'out' bằng không.
Bây giờ, để xác nhận đây chính xác là vấn đề, tôi đã sử dụng 's' của GDB (hoặc lệnh 'step') thay vì 'c' lần này. Tôi chỉ muốn dòng 11, nơi chương trình đang tạm dừng thực thi, được thực thi và xem lỗi có xảy ra tại thời điểm này không.
Đây là những gì đã xảy ra:
Đúng vậy, như đã xác nhận bằng đầu ra được tô sáng ở trên, đây là nơi ngoại lệ được ném ra. Xác nhận cuối cùng xuất hiện khi tôi thử chạy lệnh 's' một lần nữa:
Theo cách này, bạn có thể gỡ lỗi chương trình của mình bằng GDB.
Giả sử bạn là một lập trình viên C/C++ hoặc phát triển phần mềm bằng ngôn ngữ lập trình Fortran và Modula-2, trong trường hợp này, bạn sẽ vui mừng khi biết rằng có một trình gỡ lỗi tuyệt vời - được gọi là GDB - mà bạn có thể sử dụng để dễ dàng kiểm tra lỗi và các vấn đề khác trong mã của mình. Trong bài viết này, chúng ta sẽ thảo luận về những điều cơ bản của GDB và một số tính năng/tùy chọn hữu ích của nó.
Những điều cơ bản về trình gỡ lỗi GDB
Nói một cách dễ hiểu, GDB cho phép bạn xem trước chương trình khi chương trình đang thực thi, điều này giúp bạn xác định chính xác vấn đề nằm ở đâu. Chúng ta sẽ thảo luận về cách sử dụng trình gỡ lỗi GDB thông qua một ví dụ thực tế trong phần tiếp theo, nhưng trước đó, tại đây, chúng ta sẽ thảo luận về một số điểm cơ bản sẽ giúp ích cho bạn sau này.Đầu tiên, để sử dụng thành công các trình gỡ lỗi như GDB, bạn phải biên dịch chương trình của mình để trình biên dịch cũng tạo ra thông tin gỡ lỗi mà trình gỡ lỗi yêu cầu. Ví dụ, trong trường hợp trình biên dịch gcc, mà chúng ta sẽ sử dụng để biên dịch chương trình C ví dụ sau trong hướng dẫn này, bạn cần sử dụng tùy chọn dòng lệnh -g trong khi biên dịch mã của mình.
Để biết trang hướng dẫn sử dụng trình biên dịch gcc nói gì về tùy chọn dòng lệnh này, hãy truy cập tại đây.
Bước tiếp theo là đảm bảo rằng bạn đã cài đặt GDB trên hệ thống của mình. Nếu không phải vậy và bạn đang sử dụng hệ thống dựa trên Debian như Ubuntu, bạn có thể dễ dàng cài đặt công cụ bằng lệnh sau:
Mã:
sudo apt install gdb
Bây giờ, sau khi biên dịch chương trình theo cách sẵn sàng gỡ lỗi và GDB có trên hệ thống của bạn, bạn có thể chạy chương trình ở chế độ gỡ lỗi bằng lệnh sau lệnh:
Mã:
gdb [prog-executable-name]
Tiếp theo, để khởi chạy chương trình, bạn sẽ phải thực thi lệnh gdb sau:
Mã:
run
Mã:
run [arguments]
Ví dụ về cách sử dụng GDB
Bây giờ chúng ta đã có ý tưởng cơ bản về GDB cũng như cách sử dụng của nó. Vậy hãy lấy một ví dụ và áp dụng kiến thức ở đó. Sau đây là một mã ví dụ:
Mã:
#include
int main()
{
int out = 0, tot = 0, cnt = 0;
int val[] = {5, 54, 76, 91, 35, 27, 45, 15, 99, 0};
while(cnt < 10)
{
out = val[cnt];
tot = tot + 0xffffffff/out;
cnt++;
}
printf("\n Total = [%d]\n", tot);
return 0;
}
Vấn đề ở đây là khi mã được chạy, nó tạo ra kết quả sau lỗi:
Mã:
$ ./gdb-test
Floating point exception (core dumped)
Mã:
gcc -g -Wall gdb-test.c -o gdb-test
Mã:
gdb ./gdb-test
Mã:
(gdb) [B]break 11[/b]
Bây giờ, tôi yêu cầu GDB bắt đầu thực thi chương trình:
Mã:
run
Mã:
Breakpoint 1, main () at gdb-test.c:11
11 tot = tot + 0xffffffff/out;
(gdb)
Mã:
(gdb)[B] print out[/b]
[B]$1 = 5[/b]
(gdb)
Mã:
c
Mã:
...
...
...
Breakpoint 1, main () at gdb-test.c:11
11 tot = tot + 0xffffffff/out;
(gdb) print out
$2 = 99
(gdb) c
Continuing.
Breakpoint 1, main () at gdb-test.c:11
11 tot = tot + 0xffffffff/out;
(gdb) [B]print out[/b]
[B]$3 = 0[/b]
(gdb)
Đây là những gì đã xảy ra:
Mã:
(gdb) s
[B]Program received signal SIGFPE, Arithmetic exception.[/b]
0x080484aa in main () at gdb-test.c:11
11 tot = tot + 0xffffffff/out;
Mã:
(gdb) s
Program terminated with signal SIGFPE, Arithmetic exception.
The program no longer exists.