Wiki Kỹ năng giải bài Kỹ thuật debug

Kỹ thuật debug

huunguyen huunguyen Updated Tháng tư 3, 2026

Debug hiệu quả là kỹ năng quan trọng không kém thuật toán. Dưới đây là các kỹ thuật giúp bạn tìm lỗi nhanh hơn.

Quy trình debug

1. Đọc kỹ thông báo lỗi
Kết quả Nguyên nhân phổ biến
WA Sai thuật toán, sai edge case, sai kiểu dữ liệu
TLE Thuật toán quá chậm, vòng lặp vô hạn
RE Truy cập ngoài mảng, chia cho 0, stack overflow
CE Lỗi cú pháp, thiếu include
MLE Cấp phát quá nhiều bộ nhớ
2. Test với ví dụ mẫu

Chạy tay qua từng dòng code với input mẫu. So sánh kết quả trung gian với kỳ vọng.

3. Tạo test case nhỏ
// Thêm vào cuối main() để test nhanh
// Input nhỏ dễ kiểm tra bằng tay
4. In giá trị trung gian
// C++
cerr << "i=" << i << " dp[i]=" << dp[i] << "\n";

// In mảng
for (int x : a) cerr << x << " "; cerr << "\n";
# Python
print(f"i={i} dp[i]={dp[i]}", file=sys.stderr)

Dùng cerr (C++) hoặc sys.stderr (Python) để in debug mà không ảnh hưởng output.


Các lỗi thường gặp

Tràn số (Integer Overflow)
// Sai: int * int có thể tràn
int a = 1e9, b = 1e9;
int c = a * b;  // tràn!

// Đúng: dùng long long
long long c = (long long)a * b;
// Hoặc
long long c = 1LL * a * b;

Python không bị tràn số nguyên.

Truy cập ngoài mảng
// Sai: index từ 1 nhưng mảng từ 0
for (int i = 1; i <= n; i++) cout << a[i];  // a[n] out of bounds nếu a.size()==n

// Kiểm tra: luôn đảm bảo 0 <= i < a.size()
Vòng lặp vô hạn
// Sai: điều kiện không bao giờ sai
while (l <= r) {
    int mid = (l + r) / 2;
    if (check(mid)) r = mid;  // quên: nếu l==r, mid==l==r, r không đổi!
    else l = mid + 1;
}

// Đúng với l < r:
while (l < r) {
    int mid = l + (r - l) / 2;
    if (check(mid)) r = mid;
    else l = mid + 1;
}
Quên reset biến giữa các test case
// Nếu có nhiều test case:
int T; cin >> T;
while (T--) {
    // Phải reset mọi biến global/mảng trước khi dùng
    fill(dp, dp+n+1, 0);
    fill(visited, visited+n+1, false);
    // ...
}

Kỹ thuật Stress Testing

So sánh kết quả brute force với thuật toán tối ưu trên input ngẫu nhiên để tìm WA.

import random, subprocess

def brute_force(inp): ...
def fast_solution(inp): ...

for _ in range(1000):
    n = random.randint(1, 10)
    a = [random.randint(-100, 100) for _ in range(n)]
    inp = f"{n}\n{' '.join(map(str,a))}\n"

    expected = brute_force(inp)
    got = fast_solution(inp)

    if expected != got:
        print("BUG FOUND!")
        print("Input:", inp)
        print("Expected:", expected)
        print("Got:", got)
        break
else:
    print("No bugs found in 1000 tests!")

Mẹo nhanh

  • Compile với warnings: g++ -Wall -Wextra -o sol sol.cpp
  • Chạy với sanitizer (phát hiện UB, out-of-bounds): g++ -fsanitize=address,undefined
  • Python: dùng assert để kiểm tra bất biến trong code
  • Nếu bị TLE: đo thời gian từng phần để tìm nút cổ chai
  • Nếu không tìm được bug: đọc lại đề — có thể hiểu sai yêu cầu
gnatmake 12.2.0 a68g 3.1.2 nasm 2.16.1 as_x64 2.46 awk 1.3.4 gcc 16.1.0 csc 6.12.0.200 g++ 16.1.0 g++-themis 16.1.0 g++17 16.1.0 g++20 16.1.0 g++23 16.1.0 clang++ 22.1.6 dmd 2.112.0 dart 3.12.1 gforth 0.7.3 gfortran 12.2.0 go 1.26.3 groovyc 5.0.6 javac 25.0.3 node 26.2.0 kotlinc 2.3.21 sbcl 2.2.9 lua 5.4.8 nim 2.2.10 fpc 3.2.2 fpc-themis 3.2.2 perl 5.36.0 php 8.5.6 pike 8.0 pypy3 7.3.23 python3 3.14.5 racket 8.7 ruby 4.0.5 rustc 1.96.0 csc 5.3.0 ctoj-scratch 0.0.1 sed 4.9 tclsh 8.6 bun 1.3.14 deno 2.8.1 v 0.5.1 zig 0.16.0