gdb
這篇文章基本上是摘自gdb手冊(cè),除此之外就是加了實(shí)際的代碼樣例,這樣可以更清楚的看到一些命令的執(zhí)行效果。當(dāng)然,這兒不會(huì)涉及到所有的gdb命令,而只是一些常用的。
我這兒使用的gdb的版本是6.8。不過(guò)因?yàn)橹皇且恍┏S妹睿虼嗽诶习姹旧蠎?yīng)該也沒(méi)問(wèn)題。操作系統(tǒng)是Windows XP。
一.概述
調(diào)試器的目的在于讓你查看程序運(yùn)行時(shí)的內(nèi)部狀態(tài);或者在程序崩潰的時(shí)候,查看程序異常的原因。它們可以在一下幾個(gè)方面提供幫助:
1)啟動(dòng)程序,按照你的意愿影響程序的行為
2)讓程序在特定條件發(fā)生時(shí)停止運(yùn)行
3)當(dāng)程序停止的時(shí)候,檢查程序正在做什么
4)改變程序的某些東西,這樣就可以運(yùn)行時(shí)修正bug,然后繼續(xù)測(cè)試其他的問(wèn)題。
gdb支持多種語(yǔ)言的調(diào)試,不過(guò)最成熟的應(yīng)該就是c/c++了。這兒也以c++程序?yàn)槔齺?lái)說(shuō)明。如果想知道其他語(yǔ)言的支持情況,可以看gdb手冊(cè)。
二.gdb的起停
gdb最常用的啟動(dòng)方式就是:
gdb program
或者在程序異常終止的時(shí)候這樣:
gdb program core
也或者,你可以attach到一個(gè)已經(jīng)運(yùn)行的進(jìn)程來(lái)調(diào)試它,就像這樣
gdb program PID
當(dāng)然,也可以在命令行設(shè)置gdb的啟動(dòng)參數(shù),例如args:
gdb —args gcc -O2 -c foo.c
這樣就可以調(diào)試gcc,同時(shí)將參數(shù)"-O2 -c foo.c"傳給gcc。
可以用gdb -help查看gdb的所有選項(xiàng)。
要想中止gdb的運(yùn)行,可以輸入quit或者q,也可以按ctrl-d組合鍵。
三.gdb命令
命令語(yǔ)法
gdb命令的形式為:command [arg1...argn]。每個(gè)命令單獨(dú)一行。行的長(zhǎng)度沒(méi)有限制(當(dāng)然,一般應(yīng)該也不會(huì)有多長(zhǎng))。
許多gdb的命令都會(huì)有縮寫(xiě)的形式,例如break可以縮寫(xiě)為b。
如果直接按回車(chē),gdb會(huì)執(zhí)行剛剛被執(zhí)行命令。
如果命令中有#字符,那么從#開(kāi)始的字符都會(huì)被當(dāng)成是注釋。這個(gè)一般用在命令文件中。后面會(huì)有介紹。
命令補(bǔ)全
gdb具有補(bǔ)全功能。功能鍵是<TAB>。例如break,在輸入bre之后按<TAB>
鍵,gdb就會(huì)補(bǔ)全為break。如果只輸入b,然后按<TAB>,gdb會(huì)響一聲,這說(shuō)明有多個(gè)以b開(kāi)始的命令。這種情況下再按一
次<TAB>,gdb就會(huì)把所有以b開(kāi)始的命令輸出出來(lái)。下面是此時(shí)的屏幕截圖:

如果只是想看一下以某個(gè)(些)字符開(kāi)始的命令,可以按<META>?,而不用按兩次<TAB>。在沒(méi)
有<META>鍵的電腦上,可以用<ESC>鍵代替。這個(gè)命令按起來(lái)有點(diǎn)麻煩,比按兩次<TAB>要麻煩多了,如果
不怕<TAB>鍵被按壞,我建議你還是按<TAB>吧。
命令補(bǔ)全可以用于gdb命令,gdb子命令,程序中的符號(hào)名(例如函數(shù)名等)。
在調(diào)試c++程序時(shí),基本上肯定會(huì)遇到的問(wèn)題就是重載函數(shù)。例如,在設(shè)置斷點(diǎn)的時(shí)候,假設(shè)有兩個(gè)名為overload的函數(shù),這時(shí)為了區(qū)分到底是那
個(gè)函數(shù),就需要加上函數(shù)參數(shù)類(lèi)型(函數(shù)名加上參數(shù)列表作為邏輯上的一個(gè)詞)。為了使gdb能將參數(shù)列表兩邊的括號(hào)作為這個(gè)詞的一部分,需要用單引號(hào)'將函
數(shù)整個(gè)的括起來(lái)。看下圖:

獲取幫助
啟動(dòng)gdb后,可以輸入命令help得到gdb的命令列表。注意的是這時(shí)輸出的每個(gè)條目都是一類(lèi)命令。上個(gè)圖:

得到命令類(lèi)別后,可以用命令 help class得到此類(lèi)別的所有命令。上圖:

上面的圖中只顯示了部分breakpoints命令。
其他跟幫助相關(guān)的命令有:
a)help command
用于顯示命令command的幫助信息。
b)apropos args
這里的args可以使正則表達(dá)式。顯示所有匹配args的命令的簡(jiǎn)要說(shuō)明。
c)complete args
顯示所有以args開(kāi)始的命令。
另外還有兩個(gè)很有用的命令: info 和 show 。
a)info
用于顯示被調(diào)試程序的信息。例如傳遞到當(dāng)前函數(shù)的參數(shù)-info args;或者查看當(dāng)前寄存器的值-info registers;也可以查看斷點(diǎn)-info breakpoints。可以用help info查看info的說(shuō)明。
b)show
這個(gè)命令用于顯示gdb的信息。也就是gdb的一些屬性值。可以用help show查看幫助信息。這個(gè)命令通常應(yīng)該是配合set用的(用于設(shè)定gdb的屬性)。
好了,現(xiàn)在對(duì)gdb應(yīng)該有個(gè)大概的認(rèn)識(shí)了,下面我們就要拿幾個(gè)小例子來(lái)驗(yàn)證一些常用命令的效果。Let's go!
四.示例1
首先說(shuō)明一點(diǎn),要想高效的使用gdb的功能,需要在編譯程序的時(shí)候要加上-g選項(xiàng),這個(gè)選項(xiàng)會(huì)把調(diào)試信息加到可執(zhí)行文件中。
下面說(shuō)一下示例文件,包括三個(gè):gdb.h, gdb.cpp, test.cpp
gdb.h
#ifndef _GDB_H
#define _GDB_H 1
class gdb
{
public:
explicit gdb(int v);
void overload(int one);
void overload(int one, int two);
void catch_ex(int ex); //exception
void loop();
private:
int value;
int array[10];
};
#endif
gdb.cpp
#include "gdb.h"
#include <iostream>
using namespace std;
gdb::gdb(int v)
{
value = v;
for(int i=0; i<10; i++)
{
array[i] = i;
}
}
void gdb::overload(int one)
{
cout<<"function overload with one parameter: "<<one<<endl;
}
void gdb::overload(int one, int two)
{
cout<<"function overload with two paremeters: "<<one<<" "<<two<<endl;
}
void gdb::loop()
{
int loop_array[10];
for(int i=0; i<10; i++)
{
loop_array[i] = i;
}
int v=3;
v=3;
v=4;
}
void gdb::catch_ex(int ex)
{
int e = ex;
try
{
if(e <= 0)
{
throw e;
}
else
{
cout<<"function catch_ex: "<<ex<<endl;
}
}
catch(int x)
{
cout<<"exception: "<<x<<endl;
}
}
test.cpp
#include "gdb.h"
int main()
{
gdb g(5);
g.overload(1);
g.overload(1, 2);
g.loop();
g.catch_ex(3);
g.catch_ex(-1);
return 0;
}
好了,現(xiàn)在開(kāi)始調(diào)試。首先啟動(dòng)gdb,指定要調(diào)試的可執(zhí)行文件。前面已經(jīng)說(shuō)過(guò)了,可以簡(jiǎn)單地使用gdb program來(lái)啟動(dòng)。或者可以首先啟動(dòng)gdb,然后用file命令指定要調(diào)試的文件。下面是僅啟動(dòng)gdb后的畫(huà)面:

現(xiàn)在用file命令指定要調(diào)試的文件:

然后就可以用 run 或者 r 命令來(lái)運(yùn)行程序。在運(yùn)行之前,你可能需要為程序設(shè)定一些信息,這些信息有一下四種:
1)程序參數(shù)
可以用set args命令設(shè)定程序的參數(shù)。設(shè)定完后可以用show args查看設(shè)置的是否正確。如果set args后面不帶任何參數(shù),則向程序傳遞的參數(shù)為空。
2)環(huán)境
這兒的環(huán)境就是在系統(tǒng)/用戶配置文件中設(shè)置的環(huán)境變量,像HOME, PATH之類(lèi)的.GDB提供了在調(diào)試的時(shí)候改變這些變量值的方式,這樣當(dāng)需要的時(shí)候就不用退出gdb來(lái)重新設(shè)置.GDB提供的命令有:
a) path directory -- 將 directory 加到環(huán)境變量PATH前面. 注意 對(duì)PATH的改變只對(duì)調(diào)試的程序有效, GDB使用的PATH不會(huì)有改變.
b) show paths -- 顯示PATH的值。
c) show environment [varname] -- 顯示環(huán)境變量varname的值,如果不指定varname,則顯示所有環(huán)境變量的值。
d) set environment varname [= value] -- 設(shè)置環(huán)境變量varname的值為value。這個(gè)改變只是對(duì)調(diào)試的程序生效。如果不提供value,則將varname的值置為空。
e) unset environment varname -- 從環(huán)境中移除傳遞給程序的變量varname。
3)工作目錄
在啟動(dòng)gdb調(diào)試程序的時(shí)候,被調(diào)試的程序會(huì)從gdb繼承工作目錄。當(dāng)然gdb也提供了命令來(lái)修改工作目錄:
a) cd directory -- 將 directory 設(shè)為新的工作目錄。
b) pwd -- 顯示當(dāng)前工作目錄。
4)標(biāo)準(zhǔn)輸入輸出
還沒(méi)找到在windows里面這個(gè)東西有啥用,現(xiàn)在也沒(méi)有l(wèi)inux可用,不好多說(shuō)。有需要的自己看gdb手冊(cè)吧。我簡(jiǎn)單抄一下手冊(cè)吧。
在gdb中,可以將run命令的輸入輸出重定向到文件或者其他終端。也可以通過(guò)tty命令設(shè)置被調(diào)試程序輸入輸出的設(shè)備。命令格式是:
tty terminal 或者 set inferior-tty terminal.
tty 就是 set inferior-tty 的別名。
咚咚咚咚,下面正式開(kāi)始!
上面我們已經(jīng)啟動(dòng)了程序, 也知道了如何運(yùn)行程序。可是如果你直接執(zhí)行run命令會(huì)發(fā)現(xiàn),程序直接運(yùn)行結(jié)束了。如果你想在某一行或者某個(gè)函數(shù)調(diào)用的地方,或者當(dāng)某個(gè)變量/表達(dá)式的值改變的時(shí)候,也或者在某些事件發(fā)生的時(shí)候--例如拋出異常、加載動(dòng)態(tài)庫(kù),或者創(chuàng)建子進(jìn)程--的時(shí)候停止程序運(yùn)行,那應(yīng)該怎么辦呢?
有了gdb,一切就都好辦了:), 利用下面這三個(gè)強(qiáng)大的武器,你可以任意的停止程序。小心了,大家小心了,偶要祭出這三件寶物了,它們是:
斷點(diǎn)
斷點(diǎn)就是指定一個(gè)位置,使得程序運(yùn)行到這個(gè)位置的時(shí)候會(huì)停下來(lái)(當(dāng)然,還可以設(shè)置條件斷點(diǎn),當(dāng)運(yùn)行到指定位置時(shí),只有滿足了設(shè)置的條件,程序才會(huì)停下來(lái)),這樣便于觀察程序的內(nèi)部狀態(tài)。斷點(diǎn)相關(guān)的命令主要有:
a)break location
在指定位置 location 處設(shè)置斷點(diǎn),這里的 location 可以是函數(shù)名,行號(hào),指令地址等(關(guān)于如何指定 location ,可以看這里)。
b)break
如果不指定任何參數(shù),break會(huì)在選定的棧幀的下一條指令處設(shè)置斷點(diǎn)。
c)break ... if cond
設(shè)置條件斷點(diǎn)。每次到達(dá)斷點(diǎn)的時(shí)候都會(huì)對(duì)表達(dá)式 cond 求值,只有當(dāng)結(jié)果為非0的時(shí)候程序才會(huì)在這個(gè)斷點(diǎn)停下來(lái)。
d)tbreak args
設(shè)置一個(gè)只生效一次的斷點(diǎn)。args跟break命令里的參數(shù)意義相同(也就是說(shuō),可以為location,為空,或者條件)。
e)hbreak args
設(shè)置硬件斷點(diǎn)。
f)thbreak args
設(shè)置只生效一次的硬件斷點(diǎn)。
g)rbreak regex
在所有匹配正則表達(dá)式 regex 的函數(shù)上設(shè)置斷點(diǎn)。
h)info breakpoints [n]
i)info break [n]
j)info watchpoints [n]
上面三個(gè)命令都是列出當(dāng)前的斷點(diǎn)、觀察點(diǎn)和捕捉點(diǎn),如果指定參數(shù)n,則僅列出第n個(gè)的信息。
來(lái)試驗(yàn)一把吧。首先用gdb啟動(dòng)程序,假設(shè)我們想在test.cpp的 g.overload(1) 這一行添加一個(gè)斷點(diǎn),那就執(zhí)行命令:b test.cpp:6,執(zhí)行完后:

這時(shí)可以用info break等命令查看斷點(diǎn)信息:

然后我們運(yùn)行程序,看看有什么效果。

看到了吧,程序停在了斷點(diǎn)所在的行。這時(shí)可以用where或者frame查看當(dāng)前的棧幀信息,也可以用 print 查看一些變量或者表達(dá)式的信息,或者info args查看參數(shù)信息,等等。
其他的命令大家可以自己嘗試一下。
有時(shí)候我們并不確定要在哪里加斷點(diǎn),例如當(dāng)我們想在某個(gè)變量被改變或者被讀、被寫(xiě)的時(shí)候讓程序停下來(lái),可能由于訪問(wèn)變量的地方比較多,要想每個(gè)地方都加上斷點(diǎn)比較麻煩,而且很可能有遺漏,這時(shí)候我們就需要依賴另一個(gè)強(qiáng)大的命令了,也就是觀察點(diǎn)。
觀察點(diǎn)
觀察點(diǎn)是一類(lèi)特殊的斷點(diǎn),如果針對(duì)某個(gè)變量或者表達(dá)式指定一個(gè)觀察點(diǎn),那么當(dāng)它們的值被讀/寫(xiě)的時(shí)候,gdb會(huì)停止程序的執(zhí)行。你不需要像設(shè)置斷點(diǎn)時(shí)那樣明確指定這個(gè)觀察點(diǎn)在程序中的位置。觀察點(diǎn)相關(guān)的命令有:
a)watch expr [thread threadnum]
對(duì) expr 設(shè)置一個(gè)觀察點(diǎn)。當(dāng) expr 的值被改變的時(shí)候,gdb會(huì)停止程序的運(yùn)行。
如果指定了線程參數(shù)thread threadnum ,則 只有 在線程 threadnum 改變 expr 的值時(shí),程序才會(huì)停止。
b)rwatch expr [thread threadnum]
對(duì) expr 設(shè)置一個(gè)讀觀察點(diǎn)。當(dāng)程序讀 expr 的值時(shí),gdb會(huì)停止程序的運(yùn)行。
c)awatch expr [thread threadnum]
對(duì) expr 設(shè)置一個(gè)訪問(wèn)觀察點(diǎn)。當(dāng)程序讀或者寫(xiě) expr 時(shí),gdb會(huì)停止程序的運(yùn)行。
d)info watchpoints
顯示所有的斷點(diǎn)、觀察點(diǎn)、捕捉點(diǎn)。跟info break 相同。
下面再來(lái)看看觀察點(diǎn)的使用。
首先我們?cè)O(shè)置一個(gè)斷點(diǎn)在g.loop()這一行,然后運(yùn)行到這里。step進(jìn)入loop()函數(shù)。這一串命令的執(zhí)行如下:

這時(shí)我們已經(jīng)進(jìn)入loop()函數(shù),現(xiàn)在我們?cè)O(shè)置幾個(gè)觀察點(diǎn)。設(shè)置命令序列和設(shè)置完后的效果如小:

可以看到有5個(gè)停止點(diǎn),其中前兩個(gè)是我們?cè)O(shè)置的斷點(diǎn),后面三個(gè)是觀察點(diǎn)。分別為watch, rwatch 和 awatch。另外還有一個(gè)地方就是,x86上默認(rèn)是硬件觀察點(diǎn)。
好了,來(lái)運(yùn)行一下試試。

到達(dá)第一個(gè)觀察點(diǎn)的時(shí)候程序停止運(yùn)行,同時(shí)打印出了變量的舊值和新值,以及觀察點(diǎn)的位置。
下面我們接著運(yùn)行,看看遇到后面的觀察點(diǎn)的時(shí)候又會(huì)怎樣。

程序在第三個(gè)觀察點(diǎn)停了下來(lái)(第二個(gè)觀察點(diǎn)為讀觀察點(diǎn)),同樣打印出了變量的新舊值和觀察點(diǎn)的位置。第二個(gè)觀察點(diǎn)由于是讀觀察點(diǎn),而程序中沒(méi)有讀這個(gè)變量的地方,因此運(yùn)行的時(shí)候被跳過(guò)了。為了看一下讀觀察點(diǎn)的效果,我們?cè)僭O(shè)置一個(gè)讀觀察點(diǎn):

i是循環(huán)內(nèi)的迭代器,它會(huì)被復(fù)制給loop_array[i]變量,也就是會(huì)被讀。可以看到,程序會(huì)停止運(yùn)行,輸出i的值。注意:每次對(duì)i的讀操作都會(huì)使得程序停止。下面是兩次執(zhí)行continue命令后的輸出:

觀察點(diǎn)的內(nèi)容差不多就這些了。另外有個(gè)需要注意的地方就是: watch命令設(shè)置的觀察點(diǎn)只有在變量或者表達(dá)式的值被改變得時(shí)候才會(huì)使得程序停止運(yùn)行,如果只是被寫(xiě),但是值沒(méi)有改變,則程序不會(huì)停止。
上面已經(jīng)講了斷點(diǎn)、觀察點(diǎn),而對(duì)于某些情況,這兩種停止點(diǎn)并不是最有效的方式。例如想在c++程序中跑出異常的時(shí)候停
止程序,這時(shí)候用斷點(diǎn)就不夠有效了,因?yàn)槌绦蛑锌赡芎枚喈惓L幚淼牡胤剑绻粋€(gè)個(gè)設(shè)置斷點(diǎn),那就太麻煩了(當(dāng)然如果只處理某幾個(gè)異常,用斷點(diǎn)也無(wú)不可,
甚至用起來(lái)更靈活);而觀察點(diǎn)就更不可用了。
這種情況就需要用到捕捉點(diǎn)了。
捕捉點(diǎn)
捕捉點(diǎn)也是一類(lèi)特殊的斷點(diǎn),它可以使得程序在某種事件發(fā)生時(shí)停止運(yùn)行,例如c++異常,或者加載動(dòng)態(tài)庫(kù)、創(chuàng)建子進(jìn)程等。設(shè)置捕捉點(diǎn)的命令是catch.
catch event
其中 event 可以是:
a)throw
c++拋出異常。
b)catch
c++捕捉異常。
c)exception
Ada異常。
d)exception unhandled
程序中未處理的異常。
e)assert
失敗的Ada斷言。
f)exec
對(duì)exec的調(diào)用(只在HP-UX和GNU/Linux中可用)。
g)fork
對(duì)fork的調(diào)用(只在HP-UX和GNU/Linux中可用)。
h)vfork
對(duì)vfork的調(diào)用(只在HP-UX和GNU/Linux中可用)。
i)load
動(dòng)態(tài)加載共享庫(kù)(只在HP-UX中可用)。
j)load libname
動(dòng)態(tài)加載共享庫(kù) libname (只在HP-UX中可用)。
k)unload
卸載已加載的共享庫(kù)(只在HP-UX中可用)。
l)unload libname
卸載已加載的共享庫(kù) libname (只在HP-UX中可用)。
還有一個(gè)設(shè)置只生效一次的捕捉點(diǎn)的命令是: tcatch event 。
下面再看一下捕捉點(diǎn)的使用。
首先在vtest.cpp的 g.catch_ex(-1); 設(shè)置一個(gè)斷點(diǎn),然后運(yùn)行,進(jìn)入此函數(shù)。

現(xiàn)在我們?cè)O(shè)置一個(gè)捕捉點(diǎn)。繼續(xù)運(yùn)行:

可以看到程序在拋出異常的地方停止了。
刪除斷點(diǎn)
當(dāng)斷點(diǎn)不再需要了,那就應(yīng)該刪除掉,否則每次執(zhí)行到斷點(diǎn)的位置程序都要停下來(lái),會(huì)把人逼瘋的。刪除斷點(diǎn)的命令有兩個(gè):clear和delete。
a)clear [ location ]
如果不指定 location ,則刪除選擇的棧幀中下一條要執(zhí)行的指令上的任何斷點(diǎn)。如果選擇的是最內(nèi)部的棧幀(也就是當(dāng)前正執(zhí)行的函數(shù)的棧幀),則clear會(huì)將剛剛使程序停止的斷點(diǎn)被刪除。
關(guān)于 location 的說(shuō)明可以看這里。
b)delete [breakpoints] [ range ... ]
刪除指定范圍 range 那的所有的斷點(diǎn)、觀察點(diǎn)、捕捉點(diǎn)。如果不指定參數(shù) range ,則會(huì)刪除所有的停止點(diǎn)。這里的 range 指定的是斷點(diǎn)編號(hào)區(qū)間。可以用info break查看斷點(diǎn)信息。
禁用斷點(diǎn)
如果不想刪除斷點(diǎn),只是想暫時(shí)使它失效,則可以使用disable命令。disable命令的形式如下:
a)disable [breakpoints] [ range ...]
使指定區(qū)間 range 內(nèi)的斷點(diǎn)失效。如果不指定 range ,則所有的斷點(diǎn)都失效。
使斷點(diǎn)生效的命令是enable,形式有:
a)enable [breakpoints] [ range ...]
使指定區(qū)間 range 內(nèi)的斷點(diǎn)或者所有斷點(diǎn)生效。
b)enable [breakpoints] once range...
使指定區(qū)間內(nèi)的斷點(diǎn)生效一次。
c)enable [breakpoints] delete range...
使指定區(qū)間內(nèi)的斷點(diǎn)生效一次,然后刪除。
斷點(diǎn)條件
斷點(diǎn)條件使得只有在相應(yīng)的條件滿足時(shí),斷點(diǎn)才有效。這里的條件表達(dá)式跟程序所用語(yǔ)言的邏輯表達(dá)式的語(yǔ)法相同,例如在c/c++語(yǔ)言里,可以用 a==b 或者 x&&y這種表達(dá)式。
斷點(diǎn)條件可以在設(shè)置斷點(diǎn)的時(shí)候指定,也可以在斷點(diǎn)設(shè)置后通過(guò)condition命令來(lái)設(shè)置或者改變。 condition的形式為:
a)condition bnum expression
設(shè)置表達(dá)式 expression 為停止點(diǎn) bnum 的條件。
b)condition bnum
刪除停止點(diǎn) bnum 的條件。
還有一個(gè)命令,可以使得gdb忽略斷點(diǎn)的條件一定的次數(shù),其形式為:
a)ingore bnum count
指定位置
許多gdb命令都接受一個(gè)用于指定程序位置的參數(shù)。位置的指定方式有下面幾種:
a) linenum
當(dāng)前源文件的行號(hào)。
b) -offset
當(dāng)前行前面,跟當(dāng)前行間隔為 offset 的行。當(dāng)前行可以這樣確定:使用list命令,打印出來(lái)的最后一行就是當(dāng)前行;或者對(duì)于斷點(diǎn)命令,選定的棧幀中,程序停止執(zhí)行的位置就是當(dāng)前行。
c) +offset
當(dāng)前行后面,跟當(dāng)前行間隔為 offset 的行。
d) filename:linenum
源文件 filename 中的行 linenum。
e) function
當(dāng)前源文件中的函數(shù) function。
f) filename:function
源文件 filename 中的函數(shù) function。
g) * address
指定程序地址 address。常用的 address 形式有:
expression -- 當(dāng)前語(yǔ)言中有效的表達(dá)式。
funcaddr -- 函數(shù)的地址。在c/c++中就是函數(shù)名。
'filename'::funcaddr -- 源文件 filename 中的函數(shù)地址 funcaddr。
后面懶得寫(xiě)了,暫時(shí)先放一放。發(fā)現(xiàn)就算是抄文檔,內(nèi)容多了也是個(gè)很累人的活。唉,懶了,不行了...
棧
待添加
數(shù)據(jù)
待添加
五 示例2
待添加
六 后記
這篇文章只是撿了GDB中最常用的一些東西,而且還只是最常用的東西中的一小部分,有興趣或者需要的可以直接看GDB的文檔,可以在這里找到。