顯示具有 debug 標籤的文章。 顯示所有文章
顯示具有 debug 標籤的文章。 顯示所有文章

2012/08/04

工欲善其事,必先利其器:GDB 基本教學

最基本的編譯時要加"-g",把 debugging information 編譯進去,否則印不出什麼資訊來。再來就是不要做 optimize,不然程式碼行數會對不上。
$ gcc -g -o hello hello.c

啟動 GDB
$ gdb ./hello

必要時加入"-d (dirctory)"的參數,指定 source code 的位置
$ gdb -d /home/brian/test ./hello 

若程式已經在執行了,可以先查詢 pid,然後用 attach 的方式。記得 binary 的要跟正在 run 的 program 一致
$ gdb ./hello 12238

進入GDB後執行程式
(GDB) run
若要帶參數的話
run (init parameter)
Ex:
(GDB) run -h localhost -p 8080

Breakpoint
設定中斷點
b (filename):(line num)
Ex:
(GDB) b hello.c:5

列出目前的中斷點
(GDB) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x000000000040049c in main at hello.c:5

移除中斷點
d (breakpoint id)
Ex:
(GDB) d 1

列出當下的狀況
列出 function stack (Back trace)
(GDB) bt
#0  hello () at hello.c:9
#1  0x00000000004004cf in main () at hello.c:14

列出更詳細的資訊,包含 variable 的值
(GDB) bt full
#0  hello () at hello.c:9
        i = 0
#1  0x00000000004004cf in main () at hello.c:14
No locals.

列印變數
p (variable)
Ex:
(GDB) p iValue
(GDB) p *stEmployee

切換 frame。要列印區域變數時,必須要切換到正確的 frame
f (frame num)
EX:
(GDB) f 3

流程控制
Step over (不會進 function)
(GDB) n
Step into (會跳入 function)
(GDB) s
Continue
(GDB) c

Signal Handle
handle (signal) (operation)
Operation 預設為 stop print noignore,也就是遇到 signal 時,GDB 會先攔截,並中斷程式,必要時可以改為 nostop noprint,讓程式本身去處理 signal。若下達 ignore 則是讓程式忽略此 signal。
(GDB) handle SIGUSR nostop noprint

列出目前 signal 設定的狀態
(GDB) i handle
Signal        Stop      Print   Pass to program Description

SIGHUP        Yes       Yes     Yes             Hangup
SIGINT        Yes       Yes     No              Interrupt
SIGQUIT       Yes       Yes     Yes             Quit
SIGILL        Yes       Yes     Yes             Illegal instruction
SIGTRAP       Yes       Yes     No              Trace/breakpoint trap
有關 signal 的部分可以參考 http://sourceware.org/gdb

Thread
查看目前在哪個 thread
(GDB) thread

切換 thread
(GDB) thread 3

列出所有 thread 的 function stack
(GDB) thread apply all bt
(GDB) thread apply all bt full

Ref:
Examining the Symbol Table

2011/05/17

mtrace - 檢查memory leak

Memory leak中文叫內存洩漏,也是我在開發程式中一個很難搞的問題。拜一些tool所賜,讓工程師可以更容易發現問題所在。

mtrace是glibc內提供的工具,其實它的原理很簡單,就是把你程式中malloc()與free()的位址全部下來,最後兩兩配對,殘留下來沒有配對到的就是leak。

1. 安裝glibc-utils

2. 在程式中include header file並在程式最前面call mtrace()
e.g. test.c
#include 
#include 

int main(void) {
    char *p;

    mtrace();
    p = malloc(5);  // 要一塊記憶體,但沒有釋放

    return 0;
}

3. compile
$ gcc -g -o test test.c
一定要加-g

4. run program
$ MALLOC_TRACE=output.log ./test
MALLOC_TRACE指向output file

5. 抓leak
$ mtrace ./test ./output.log
結果:
Memory not freed:
-----------------
           Address     Size     Caller
0x0000000000c2d460      0x5  at /tmp/test.c:8
很清楚看到test.c第8行allocate 5 byte未釋放

--

不過mtrace算是很陽春的工具,如果是間接allocte記憶體,如call object_new()這種init function,那mtrace就沒辦法表示得那麼清楚了。
e.g. test2.c
#include 
#include 
#include 

int main(void) {
    GHashTable *ht;

    mtrace();
    ht = g_hash_table_new(NULL, NULL);

    return 0;
}

執行mtrace結果:
Memory not freed:
-----------------
           Address     Size     Caller
0x0000000012a24460     0xfc  at 0x2b267c24f3b1
0x0000000012a24570    0x1f8  at 0x2b267c24f3b1
0x0000000012a24770    0x1f8  at 0x2b267c24f3b1
0x0000000012a24970    0x7f0  at 0x2b267c24f3b1
0x0000000012a25170     0xc0  at 0x2b267c24f3b1
0x0000000012a25400    0x3f0  at 0x2b267c262ce1
0x0000000012a25800    0x3f0  at 0x2b267c262ce1

這樣的訊息對我們來說沒什麼幫助,這時候可以借助更強大的工具valgrind或heap checker。

2011/05/16

pstack - 列印出process stack trace

有時候遇到process hang住了,我們想知道各thread目前function call stack為何就可以利用pstack。使用前提是binary還保有symbol(還未strip)

用法︰
$  pstack pid

e.g.
$ pstack `pgrep syslog-ng`

Backtrace for pid 21374
A syntax error in expression, near `'.
#0  0x00000034bb6cb14f in poll () from /lib64/libc.so.6
#1  0x0000000000402957 in main_context_poll (ufds=0x9b1920, nfsd=22,
    timeout_=14303) at main.c:134
#2  0x00002b3ba086a90f in g_main_context_poll (context=0x966400, block=1,
    dispatch=1, self=) at gmain.c:3093
#3  g_main_context_iterate (context=0x966400, block=1, dispatch=1,
    self=) at gmain.c:2775
#4  0x00002b3ba086af0b in g_main_context_iteration (context=0x966400,
    may_block=1) at gmain.c:2843
#5  0x0000000000402421 in main_loop_run (cfg=0x7ffff43c6040) at main.c:170
#6  0x00000000004028d9 in main (argc=1, argv=0x7ffff43c6138) at main.c:448
這個訊息跟在gdb下thread apply all bt是一樣的。

下載︰
我只找到Oracol Project: GDB pstack