1. 程式人生 > >linux gdb除錯

linux gdb除錯

gdb除錯常用的命令

1.顯示程式中的當前位置和表示如何到達當前位置的棧跟蹤bt,  where,  info stack;這三個的功能都是一樣的,在程式崩潰之後使用該命令檢視堆疊的歷史記錄,很管用。

用法:

bt n: 顯示程式棧頂的n幀資訊;

bt -n: 顯示程式棧底的n幀資訊;

frame n: 檢視第n幀的簡要資訊;


2.info: 獲取和被除錯程式的相關資訊;

info frame或info frame n: 檢視幀或第n幀的詳細資訊;

info locals: 檢視當前幀中的區域性變數資訊;


3.list: 檢視執行位置的程式碼;

list n: 檢視當前檔案中第n行周圍的原始碼;

list func: 檢視函式func周圍的原始碼;


4.print:打印表達式或者變數的資訊。

用法:p [/format] exptr;

p temp: 列印變數temp的值;

p /x temp: 按十六進位制的形式列印變數temp的值;

------------------------------------------------------------------

format的取值範圍有如下幾種:

  • x 按十六進位制格式顯示變數。
  • d 按十進位制格式顯示變數。
  • u 按十六進位制格式顯示無符號整型。
  • o 按八進位制格式顯示變數。
  • t 按二進位制格式顯示變數。
  • a 按十六進位制格式顯示變數。
  • c 按字元格式顯示變數。
  • f 按浮點數格式顯示變數。

------------------------------------------------------------------

5.檢視函式的返回值資訊:

a.執行finish至函式結束,此時會自動打印出函式的返回值;

(gdb)finish
    Run till exit from #0 foo () at main.c:9
    main () at main.c:15
    15 }
    Value returned is $2 = 100

b.函式返回值會儲存在暫存器eax中,可以直接檢視該暫存器的值:

(gdb)p $eax
    $3 = 100

    (gdb) info registers
    eax 0x64 100


6.檢視記憶體:

examine命令(簡寫x): x /(n/f/u) <addr>;

  • n 表示顯示記憶體的長度,也就是說從當前地址向後顯示幾個地址的內容。-----------顯示的變數的個數
  • f 表示顯示的格式,如果是字串,則用s,如果是數字,則可以用i。
  • u 表示從當前地址往後請求的位元組數,預設是4個bytes。(b單位元組,h雙位元組,w四位元組,g八位元組)--------指定每個變數所佔用的位元組數
  • <addr> 表示一個記憶體地址。

例如:以兩位元組為單位顯示陣列arr的地址後32位元組記憶體資訊如下.

    (gdb)x /16uh arr
    0xbffff4cc: 2 0 4 0 6 0 8 0
    0xbffff4dc: 10 0 34032 2052 0 0 0 0

特殊的檢視方式:連續記憶體的檢視;

可以使用GDB的"@"操作符檢視連續記憶體,"@"的左邊是第一個記憶體的地址的值,"@"的右邊則你你想檢視記憶體的長度。

例如,對於如下程式碼:int arr[] = {2, 4, 6, 8, 10};,可以通過如下命令檢視arr前三個單元的資料。

    (gdb)p *[email protected]
    $2 = {2, 4, 6}


7.設定斷點:

a.非條件斷點:break test.cpp:10(在test.cpp檔案的第10行設定一個斷點);

b.條件斷點:break test.cpp:38 if count==3(在test.cpp的第38行設定一個斷點,如果程式執行到這裡的時候count為3,則程式將暫停執行);

c.“break main”:在main函式入口設定斷點,可以從程式一開始執行就跟蹤除錯程式碼;


8.檢視變數的型別:whatis;

whatis p: 檢視p的型別;

9.在不同的呼叫上下文中切換棧幀:frame;

frame num:切換到棧幀號為num的棧中;

在分析核心檔案時,通過將遍歷棧的命令和檢查變數值的“print”命令結合起來,就能夠復原程式執行時的全部景象。


10.除錯正在執行的程序:有些程序可能無法直接在偵錯程式上執行,可以通過下面的方式來除錯這些程序

一種是在GDB命令列上指定程序的PID:先執行程式dataserverhq,然後通過ps -aux | grep dataserverhq獲取程式的pid,最後在另外一個開啟的shell中執行gdb dataserverhq pid;


第二種先用file命令載入除錯時所需的符號表,然後再通過“attaché”命令進行連線

(gdb) file /home/xiaowp/debugme Reading symbols from /home/xiaowp/debugme...done. 
(gdb) attach 555 ……

除錯結束結束時,用detach斷開連線,讓被除錯的程序可以繼續正常執行下去。


11.載入需要除錯的程式

第一種方法:gdb dataserverhq;

第二種方法:gdb; file dataserverhq;

第三種方法: gdb attach process_pid;


12.恢復程式執行,直到程式結束(從斷點處繼續執行):continue, c, fg;


13.顯示呼叫和執行一個函式:call function(arg1, arg2,...);


14.結束當前迴圈:until, u;


15.使用info threads 可以檢視執行的執行緒.

thread num: 切換到執行緒號為num的執行緒;


16.檢視當前棧層的資訊:frame, f;


17.info f(或者info frame):打印出更為詳細的當前棧層的資訊;


18.強制函式返回:

如果你的除錯斷點在某個函式中,並還有語句沒有執行完。你可以使用 return 命令強制函式忽略還沒有執行的語句並返回。


-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

還有就是裡面某個執行緒停住,也沒死,這種情況一般就是死鎖或者涉及訊息接受的超時問題(聽人說的,沒有遇到過)。遇到這種情況,可以使用:
gcore pid (除錯程序的pid號)
手動生成core檔案,在使用pstack(linux下好像不好使)檢視堆疊的情況。

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


gdb的tui(terminal user interface)方法除錯程式碼:

前提:程式碼跟執行的程式需要在同一臺主機上,不然找不到原始碼

開啟/關閉方式:ctrl+x+a;

啟動方式:gdb -tui ./dataserverhq;