Kỹ thuật GDB nâng cao cho lập trình thi đấu

Bài viết này giới thiệu các kỹ năng sử dụng GDB hiệu quả trong môi trường lập trình thi đấu. Nội dung tập trung vào các lệnh ít phổ biến nhưng cực kỳ hữu ích khi debug chương trình C++. Mọi ví dụ đều giả định bạn đã biết cơ bản về GDB và đã biên dịch với cờ -g.

Mã nguồn mẫu

#include <iostream>
#include <vector>

int tinhFibonacci(int k) {
    if (k <= 1) return k;
    return tinhFibonacci(k - 1) + tinhFibonacci(k - 2);
}

int main() {
    int soLuong;
    std::cin >> soLuong;
    
    std::vector<int> daySo(10, 0);
    for (int i = 0; i < soLuong && i < 10; ++i) {
        daySo[i] = tinhFibonacci(i);
    }
    
    std::cout << "Gia tri: " << daySo[soLuong-1] << std::endl;
    return 0;
}

Cấu hình tối ưu

Thêm các dòng sau vào file ~/.gdbinit để GDB hoạt động tốt hơn:

set max-value-size unlimited
set print pretty on
set print array-indexes on
set confirm off
set pagination off

1. Điều hướng ngăn xếp với backtrace

Lệnh bt hiển thị thông tin các khung ngăn xếp, đặc biệt hữu ích khi debug đệ quy.

(gdb) bt
#0  tinhFibonacci (k=3) at fibo.cpp:5
#1  0x00005555555551ce in tinhFibonacci (k=4) at fibo.cpp:6
#2  0x00005555555551ce in tinhFibonacci (k=5) at fibo.cpp:6
#3  0x0000555555555257 in main () at fibo.cpp:14

Các lệnh liên quan:

  • up [so_khung]: Di chuyển lên khung cha
  • down [so_khung]: Di chuyển xuống khung con
  • frame [so_hieu]: Chuyển trực tiếp đến khung có số hiệu

2. Tự động hóa với commands

Lệnh comm thực thi các lệnh GDB tự động khi gặp breakpoint.

(gdb) b 14
Breakpoint 1 at 0x555555555257: file fibo.cpp, line 14.
(gdb) comm 1
>print "Dang tinh day so..."
>print daySo[i]
>end

3. Bỏ qua breakpoint tạm thời

Lệnh ignore (viết tắt ig) cho phép bỏ qua breakpoint trong một số lần đầu.

(gdb) b 6
Breakpoint 2 at 0x5555555551ce: file fibo.cpp, line 6.
(gdb) ig 2 8
Will ignore next 8 crossings of breakpoint 2.

4. Điều kiện dừng linh hoạt

Lệnh cond đặt điều kiện cho breakpoint chỉ dừng khi điều kiện đúng.

(gdb) b 6
Breakpoint 3 at 0x5555555551ce: file fibo.cpp, line 6.
(gdb) cond 3 k==7
(gdb) r
Breakpoint 3, tinhFibonacci (k=7) at fibo.cpp:6

5. Các loại breakpoint đặc biệt

  • tbreak (tb): Breakpoint tạm, tự xóa sau khi dừng
  • rbreak (rb): Đặt breakpoint theo biểu thức chính quy
(gdb) tb tinhFibonacci
Temporary breakpoint 4 at 0x5555555551a8: file fibo.cpp, line 5.
(gdb) rb tinh*
Breakpoint 5 at 0x5555555551a8: file fibo.cpp, line 5.

6. In dữ liệu đa dạng

6.1 Định dạng xuất

Ký tựĐịnh dạng
xThập lục phân
dThập phân có dấu
uThập phân không dấu
tNhị phân
cKý tự
fSố thực
(gdb) p/t 42
$1 = 101010
(gdb) p/x 255
$2 = 0xff

6.2 In phần tử mảng

Dùng cú pháp mang[chi_so]@so_luong để in số lượng phần tử xác định.

(gdb) p daySo[0]@5
$3 = {0, 1, 1, 2, 3}

7. Lưu và khôi phục breakpoint

Lưu breakpoint vào file: save breakpoints ten_file
Nạp lại breakpoint: source ten_file

(gdb) save breakpoints gdb_session
Saved to file 'gdb_session'.
(gdb) quit
...
(gdb) source gdb_session

8. Gọi hàm trong phiên debug

Lệnh call thực thi hàm ngay trong GDB.

(gdb) call tinhFibonacci(10)
$4 = 55

9. Thực thi đến khi kết thúc hàm

Lệnh fin tiếp tục chạy đến khi hàm hiện tại trả về.

(gdb) fin
Run till exit from #0 tinhFibonacci (k=5) at fibo.cpp:6
0x0000555555555257 in main () at fibo.cpp:14

10. Giám sát biến với watchpoint

Lệnh watch dừng khi biến bị thay đổi.

(gdb) watch soLuong
Hardware watchpoint 6: soLuong
(gdb) c
Hardware watchpoint 6: soLuong

Old value = 0
New value = 8
main () at fibo.cpp:11

11. Chụp ảnh trạng thái với checkpoint

Tạo checkpoint: checkpoint (viết tắt ch)
Quay lại checkpoint: restart [so_hieu]

(gdb) checkpoint
checkpoint 1: fork returned pid 28471.
(gdb) restart 1

12. Nhảy và ép buộc trả về

jump [dong]: Chuyển đến dòng code cụ thể
return [gia_tri]: Kết thúc hàm hiện tại và trả về giá trị

(gdb) jump 16
(gdb) return 999

Thẻ: GDB debugger c-plus-plus competitive-programming debugging-tools

Đăng vào ngày 30 tháng 8 lúc 09:19