K thut Debug trong C
nvhoang@fit.hcmuns.edu.vn.
Đối vi lp trình viên, vic đề ra ý tưởng để gii quyết vn đề đã là khó khăn, nhưng vic
cài đặt được ý tưởng đó cũng không đơn gin. Đôi khi ch vì mt du ; hay sai kiu d
liu cũng có th biến bn cài đặt tr nên vô nghĩa vì không th hin đúng ý tưởng đề ra.
Nhưng làm sao để phát hin ra mt con sâu (li-bug) trong mt “rng lnh? Câu tr li
rt đơn gin nhưng khó thc hin : chúng ta phi kiên nhn “vch lá tìm sâu ! Đó là lý
do ti sao chúng ta phi nm k thut debug.
Bài viết này nhm hướng dn các bn s dng k thut debug để tìm li thông qua vic
phân tích các ví d, đồng thi cũng đưa ra mt s bài tp t d đến khó để các bn có th
tng bước nm vng k thut debug.
1 Các loi li trong chương trình:
1.1 Li sai cú pháp:
Đây là nhng li sai xy ra khi biên dch chương trình (sau khi nhn F9). Khi gp
li này, chúng ta nên nhn Ctrl-F1 để gi giúp đỡ hoc xem li tài liu tham kho. đây
không để cp chi tiết đến vn đề này.
1.2 Li sai logic:
1.2.1 Khái nim :
Các li sai logic là nhng li khi biên dch, trình biên dch không báo li. Nhng li
này nm tim n trong chương trình và làm cho chương trình ca chúng ta đưa ra nhng
kết qu không như mong mun.
Các li sai logic thường xut phát t 2 nguyên nhân :
- Do nhm (nhm ch không sai) cú pháp dn đến sai logic.
- Do ý tưởng để gii quyết bài toán đã sai ngay t đầu.
Loi li này bình thường rt khó nhn ra. Dĩ nhiên, nếu tinh ý đôi khi chúng ta vn có
th phát hin ra nhng li này, nhưng vic phát hin này đòi hi chúng ta phi nm rt
vng cú pháp C, cũng như logic ca chương trình cng thêm mt chút kinh nghim. Tuy
nhiên, trong đa s các trường hp chúng ta phi thc hin công đon debug để tìm ra các
li sai logic này.
1.2.2 Mt s ví d v li sai logic :
Sau đây là mt s ví d v li sai logic:
VD1 : Xét hàm hoán v 2 s nguyên
void HoanVi(int a, int b)
{
int c = a;
a = b;
b = c;
}
Thot nhìn, chúng ta hàm này không có vn đề gì c ! Nhưng nếu tinh ý mt chút chúng
ta s thy ch truyn tham s ca hàm là sai, đây là cách truyn tham tr ch không phi
truyn tham biến, do đó giá tr ca a, b s không thay đổi sau khi hàm thc hin xong.
Chúng ta phi sa li như sau :
void HoanVi(int &a, int &b)
{
int c = a;
a = b;
b = c;
}
VD2 : Xét hàm sp xếp mng mt chiu các s nguyên theo th t tăng dn
/*
Hàm sp xếp mng
Tham s vào :
n – s lượng s nguyên
a - mng mt chiu các s nguyên, t a[0]...a[n-1]
*/
void SapXepMangTangDan(int n, int a[])
{
int i, j;
for (int i = 0; i < n; i++);
for (int j = 0; j < n; j++)
if (a[i] > a[j])
HoanVi(a[i], a[j]);
}
Nếu như chúng ta chưa tng gõ đon mã hàm sp xếp thì có l chúng ta khó phát hin ra
ch sai. Nhưng cho như vy chúng ta vn có th phát hin ra dòng lnhfor (int
i = 0; i < n; i++); là có vn đề, ti sao li có du ; cui dòng lp for ?
Nhưng cho bn có b du ;đi thì hàm này vn sai. Trong trường hp này chúng ta
bt buc phi debug để loi đi nhng li logic.
Các bn có th tham kho phc lc để xem mt s li sai logic thường gp.
2 Cơ chế thc thi chương trình :
Để có th thc hin công vic debug, trước hết chúng ta s tìm hiu cơ chế thc thi ca
mt chương trình C.
(Để cho đơn gin, tôi xin phép ch trình bày vic thc thi mc ngôn ng C, ch không
trình bày mc ngôn ng assembly).
Cơ chế chính thc thi trong chương trình C là thc thi tng dòng lnh t trên xung
dưới, ch khi gp nhng lnh r nhánh (if), nhng lnh lp (for, while), nhng li gi
hàm, hay lnh nhy (goto) thì C s chuyn đến thc thi dòng lnh đã được ch định, ri
li tuân theo cơ chế t trên xung dưới. C luôn luôn bt đầu thc thi t hàm main().
2.1 Cơ chế chính ca vic thc thi :
1 #include <stdio.h>
2 #include <conio.h>
3 void main()
4 {
5 clrscr();
6 printf(“Đây là chương trình ví d\n”);
7 getch();
8 }
Như đã nói trên, C s bt đầu thc thi chương trình t hàm void main() : dòng lnh 4. Sau
đó C s tiếp tc thc thi t trên xung dưới. Tc là tiếp tc thc thi dòng lnh 5 : clrscr(),
ri đến dòng lnh 6 : printf , ri đến dòng lnh 7 : getch(). Sau khi thc thi xong dòng
lnh 8 : du}, không còn gì thc thi na C s kết thúc vic thc thi.
2.2 Các lnh if...else, while, do..while :
Các lnh này các có tham kho lý thuyết, xin phép không nêu ra đây. Tuy nhiên, có mt
vài lưu ý sau :
- Các lnh lp cũng được thc thi theo cơ chế t trên xung dưới, nhưng khi đến cui
khi lnh lp, C s quay li đầu khi để thc thi (nếu biu thc điu kin trong while
tha)
- Sau khi thc thi xong các lnh này (tc là các biu thc trong if, while đều thc thi
xong), C s tiếp tc thc thi khi lnh ngay tiếp sau nhng lnh này.
VD : Nhp mt mng các s nguyên dương A, vic nhp kết thúc khi nhp mt s âm.
Sau đó kim tra xem dãy A đó có tăng hay không, xut ra màn hình DÃY TĂNG hoc
DÃY KNG TĂNG.
#include <stdio.h>
#include <conio.h>
Th
c thi t tr
ên
xung dưới, bt
đầu t hàm
main()
1 void main()
2 {
3 int a[100]; // mang cac so nguyen duong
4 int n; // so luong phan tu
5 int x;
6 int daytang;
7 clrscr();
8
9 // nhap
10 n = 0;
11 do
12 {
13 printf("nhap a[%d] : ", n);
14 scanf("%d", &x);
15 if (x >= 0)
16 {
17 a[n] = x;
18 n++;
19 }
20 }
21 while (x >= 0);
22 // xu ly
23 daytang = 1; // gia su day tang
24 for (int i = 0; i < n-1; i++)
25 if (a[i] > a[i+1]) // kiem tra tinh tang
26 daytang = 0;
27 // xuat
28 if (daytang)
29 printf("DAY TANG\n");
30 else
31 printf("DAY KHONG TANG\n");
32
33 getch();
34 }
Đầu tiên C s bt đầu thc hin t hàm main() (ng 1).
Xét khi C thc hin ti vòng lp do...while (dòng 11). C s ln lượt thc hin các dòng
lnh 12, 13, 14. Đến dòng 15 là dòng lnh if, C s tính toán xem (x >= 0) hay không, nếu
x >= 0 C s tiếp tc thc thi dòng lnh 17, 18, 19, ri sang dòng 20, còn nếu x < 0 thì C
s chuyn sang thc thi dòng 20 (xin lưu ý dòng 20 chính là lnh tiếp sau lnh if).
Khi C thc hin ti dòng 21, chính là cui khi lnh do..while, C s kim tra biu thc
điu kin trong while (x >= 0), nếu biu thc này tha C s quay li lnh 11, nếu không C
s thc hin lnh 23.
Khi C thc hin ti dòng 24 : lnh lp for. Đầu tiên C s thc hin int i = 0. Sau đó kim
tra i < n-1, nếu đúng thì qua dòng 25, nếu không thì kết thúc dòng for (dòng 28).
Khi đến dòng 25 : lnh r nhánh if, C s kim tra điu kin (a[i] > a[i+1]) nếu đúng thì
qua dòng 26 ri kết thúc lnh if, còn nếu sai thì cũng thúc lnh if. Nhưng do lnh if nm
trong for cho nên C s tiếp tc thc thi dòng for, tc là quay li dòng 24.
Các đon sau tương t như trên.
2.3 Lnh gi hàm :
Khi gp mt lnh gi hàm f, C s thc thi như sau :
Đầu tiên C s di chuyn đến đầu hàm f và thc thi t trên xung dưới hàm này. Sau khi
thc thi xong hàm, C s quay tr li thc thi lnh ngay sau lnh gi hàm. Qui trình
được din t trong sơ đồ sau :
3 Cách s dng debug trong Borland C++ 3.1 :
Đây là các chc năng ng để debug trong BC3.1
Phím tt Chc năng Ý nghĩa
F7 Trace into Dò tng dòng lnh mt. Nếu gp hàm thì s dò vào
trong hàm.
F8 Step over Tương t Trace into, nhưng không dò vào trong
hàm.
F4 Go to cursor Yêu cu C thc thi cho đến khi gp dòng lnh ngay
ti v trí con tr thì ngng để dò vết.
Ctrl-F8 Breakpoint Đặt nhng đim dng tương t như F4.
Ctrl-F2 Program reset Dng vic debug.
Đây là bng các chc năng xem giá tr trong khi debug.
Phím tt Chc năng Ý nghĩa
Ctrl-F4 Evaluate/Modify Xem giá tr ca mt biu thc có các biến hin thi
hoc sa giá tr ca mt biến
Ctrl-F7 Watch Đưa mt biến/biu thc vào ca s watch để theo
dõi khi debug.
....
void f()
{
}
....
void main()
{
....
f();
lnh;
...
}
1
2
3
4