Linux程式設計時有個很重要的Debug工具─GNUU Debuger, GDB。GDB可以讓成是隨時停下,印出變數。此外也可以逐行追蹤,所具備的Debug功能完整。
若要使用GDB,則程式用gcc編譯時就得加上-g選項。而事實上,gcc有三種GDB的debug等級:
- g (default, ggdb2)
- ggdb
- ggdb2
- ggdb3
Note:
Level 1 produces minimal information, enough for making backtraces in parts of the program that you don't plan to debug. This includes descriptions of functions and external variables, but no information about local variables and no line numbers.
Level 3 includes extra information, such as all the macro definitions present in the program. Some debuggers support macro expansion when you use `-g3'.
An example:
Build Code, test.c
int main()
{
int var1, var2, var3;
var1=1;
var2=2;
var3 = var1+var2;
return 0;
}
Compile
gcc -Wall -g -o test test.c
其中-g是指debug等級。
Debug mode
gdb -q test
一進入gdb mode後每個line前面都會出現(gdb)可以輸入指令。
(gdb)模式下的指令
1. list (簡寫l)
可以印程式的每個line編號。
2. breakpoint + line行數 (簡寫b line行數)
程式執行道該行會停下。
3. run (簡寫r)
程式開始跑。
4. next (簡寫n)
程式繼續執行下一行。
5. continue (簡寫c)
程式不斷執行下去直到遇到break point。
6. print 變數 (簡寫 p 變數)
程式印出該變數。
懂了以上指令後,可以執行一個簡單範例,以test.c為例。
test.c範例
(gdb) l
1 int main()
2 {
3 int var1, var2, var3;
4 var1=1;
5 var2=2;
6 var3 = var1+var2;
7 return 0;
8 }
(gdb) b 2
//會在line 2停下。
(gdb) n
//會執行到line 3停下。
(gdb) n
//會執行到line 4停下。
(gdb) p var1
$1 = 1
//會把var1印出。
(gdb) c
//會執行到line 7結束。
緊接者,我們考慮一個問題,如果要監控一個變數且讓程式不間斷的跑這件事情要如何做到?
這時候需要介紹一個新GDB指令,commands。
commands的功能就像Scripts,他可以讓GDB自動去執行該Scripts。
cammnds範例
(gdb) l
1 int main()
2 {
3 int var1, var2, var3;
5 var1=1;
6 var2=2;
7 for (;;){
8 var3 = var1+var2;
9 }
7 return 0;
8 }
(gdb) commands
>> b 8 //在line 8新增break points
>> p var3 //印出 var3
>> c //繼續執行
>> end //commands結束
(gdb) r //開始執行
但是如果單純只打這樣的指令,讀者會發現,每次當var 3印滿一頁(terminal)時,程式就會停下詢問要不要繼續往下印。
如果我們希望可以不斷的把訊息截出來,且不要印到一半停住,此時可以在進入模式(gdb)後,就下set pagination off指令。
Note that set pagination 在 initial是on的狀態。
在考慮另外一種情境,如果我們不希望印出太多數字,只希望變數改變時印出來。那該如何實現?
這時需要watch指令的配合,watch的變數只有在變數改變時會輸出到terminal。
cammnds/watch範例
(gdb) l
1 int main()
2 {
3 int var1, var2, var3, count;
5 var1=1;
6 var2=2;
7 count = 0;
8 for (;;){
9 if (count == 100) count=0;
10 if(count%2==0)
11 var3 = var1+var2;
12 count++;
13 }
14 return 0;
15 }
>> watch var3 //印出 var3 if var3改變
(gdb) r //開始執行
另外,如果想要強制改變變數內容可以使用set指令。
set範例
(gdb) l
1 int main()
2 {
3 int var1, var2, var3;
4 var1=1;
5 var2=2;
6 var3 = var1+var2;
7 return 0;
8 }
(gdb) b 2
//會在line 2停下。
(gdb) set var1=20
//把var1設成20。
(gdb) p var1
從上面範例可以看到var1會變強制設成20。
(gdb) commands
>> c //繼續執行
>> end //commands結束
>> b 11 //在line 11新增break points