linux gdb調(diào)試

姓名:曾國強

學號:19021210984

轉(zhuǎn)載自https://blog.csdn.net/huangjingbin/article/details/38866691

【嵌牛導讀】gdb是linux下非常好用的一個調(diào)試工具,它是一個用來調(diào)試c、c++程序的功能強大的調(diào)試器,它能夠在程序運行的過程中觀察程序的內(nèi)部結(jié)構(gòu)和內(nèi)存的使用情況疯趟。程序員也可以使用gdb來跟蹤程序中的錯誤勋篓,從而減少了程序員的工作量惜互。

【嵌牛正文】

一、gdb常用命令

l:查看文件

b:設置斷點(b 10瘾英,b 函數(shù)名)

clear:刪除斷點(clear 行號熏矿,clear 函數(shù)名)

delete:刪除所有斷點

info b:查看斷點情況

r:運行代碼

p 變量名:查看變量值

p/x 變量名:按格式產(chǎn)看變量值(x16進制已骇;d十進制;o八進制票编;t二進制;c字符卵渴;f浮點數(shù))

n:單步運行(不進入子函數(shù))

s:單步運行(進入子函數(shù))

c:恢復程序運行

set args 參數(shù):向程序傳參

二慧域、gdb學習實例

#include <stdio.h>

int add_range(int low, int high)

{ int i, sum;

for (i = low; i <= high; i++)

sum = sum + i;

return sum;

}

int main(void)

{ int result[100];

result[0] = add_range(1, 10);

result[1] = add_range(1, 100);

printf("result[0]=%d\nresult[1]=%d\n", result[0], result[1]);

return 0;

}

add_range函數(shù)從low加到high,在main函數(shù)中首先從1加到10浪读,把結(jié)果保存下來昔榴,然后從1加到100,再把結(jié)果保存下來碘橘,最后打印的兩個結(jié)果是:

result[0]=55

result[1]=5105

第一個結(jié)果正確[20]互订,第二個結(jié)果顯然不正確,在小學我們就聽說過高斯小時候的故事痘拆,從1加到100應該是5050仰禽。一段代碼,第一次運行結(jié)果是對的,第二次運行卻不對吐葵,這是很常見的一類錯誤現(xiàn)象规揪,這種情況不應該懷疑代碼而應該懷疑數(shù)據(jù),因為第一次和第二次運行的都是同一段代碼温峭,如果代碼是錯的猛铅,那為什么第一次的結(jié)果能對呢?然而第一次和第二次運行時相關(guān)的數(shù)據(jù)卻有可能不同凤藏,錯誤的數(shù)據(jù)會導致錯誤的結(jié)果奸忽。在動手調(diào)試之前,讀者先試試只看代碼能不能看出錯誤原因揖庄,只要前面幾章學得扎實就應該能看出來栗菜。

在編譯時要加上-g選項,生成的可執(zhí)行文件才能用gdb進行源碼級調(diào)試:

$ gcc -g main.c -o main

$ gdb main

GNU gdb 6.8-debian

Copyright (C) 2008 Free Software Foundation, Inc.

License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software: you are free to change and redistribute it.

There is NO WARRANTY, to the extent permitted by law.? Type "show copying"and "show warranty" for details.

This GDB was configured as "i486-linux-gnu"...

(gdb)?

-g選項的作用是在可執(zhí)行文件中加入源代碼的信息抠艾,比如可執(zhí)行文件中第幾條機器指令對應源代碼的第幾行苛萎,但并不是把整個源文件嵌入到可執(zhí)行文件中,所以在調(diào)試時必須保證gdb能找到源文件检号。gdb提供一個類似Shell的命令行環(huán)境腌歉,上面的(gdb)就是提示符,在這個提示符下輸入help可以查看命令的類別:

(gdb) help

List of classes of commands:

aliases -- Aliases of other commands

breakpoints -- Making program stop at certain points

data -- Examining data

files -- Specifying and examining files

internals -- Maintenance commands

obscure -- Obscure features

running -- Running the program

stack -- Examining the stack

status -- Status inquiries

support -- Support facilities

tracepoints -- Tracing of program execution without stopping the program

user-defined -- User-defined commands

Type "help" followed by a class name for a list of commands in that class.

Type "help all" for the list of all commands.

Type "help" followed by command name for full documentation.

Type "apropos word" to search for commands related to "word".

Command name abbreviations are allowed if unambiguous.

也可以進一步查看某一類別中有哪些命令齐苛,例如查看files類別下有哪些命令可用:

(gdb) help files

Specifying and examining files.

List of commands:

add-shared-symbol-files -- Load the symbols from shared objects in the dynamic linker's link map

add-symbol-file -- Load symbols from FILE

add-symbol-file-from-memory -- Load the symbols out of memory from a dynamically loaded object file

cd -- Set working directory to DIR for debugger and program being debugged

core-file -- Use FILE as core dump for examining memory and registers

directory -- Add directory DIR to beginning of search path for source filesedit -- Edit specified file or function

exec-file -- Use FILE as program for getting contents of pure memory

file -- Use FILE as program to be debugged

forward-search -- Search for regular expression (see regex(3)) from last line listed

generate-core-file -- Save a core file with the current state of the debugged process

list -- List specified function or line...

現(xiàn)在試試用list命令從第一行開始列出源代碼:

(gdb) list 1

1 #include <stdio.h>

2

3 int add_range(int low, int high)

4 {

5 int i, sum;

6 for (i = low; i <= high; i++)

7 sum = sum + i;

8 return sum;

9 }

10

一次只列10行翘盖,如果要從第11行開始繼續(xù)列源代碼可以輸入

(gdb) list

也可以什么都不輸直接敲回車,gdb提供了一個很方便的功能凹蜂,在提示符下直接敲回車表示重復上一條命令馍驯。

(gdb) (直接回車)

11 int main(void)

12 {

13 int result[100];

14 result[0] = add_range(1, 10);

15 result[1] = add_range(1, 100);

16 printf("result[0]=%d\nresult[1]=%d\n", result[0], result[1]);

17 return 0;

18

gdb的很多常用命令有簡寫形式,例如list命令可以寫成l玛痊,要列一個函數(shù)的源代碼也可以用函數(shù)名做參數(shù):

(gdb) l add_range

1 #include <stdio.h>

2

3 int add_range(int low, int high)

4 {

5 int i, sum;

6 for (i = low; i <= high; i++)

7 sum = sum + i;

8 return sum;

9 }

10

現(xiàn)在退出gdb的環(huán)境:

(gdb) quit

我們做一個實驗汰瘫,把源代碼改名或移到別處再用gdb調(diào)試,這樣就列不出源代碼了:

$ mv main.c mian.c

$ gdb main...

(gdb) l

5 main.c: No such file or directory.

in main.c

可見gcc的-g選項并不是把源代碼嵌入到可執(zhí)行文件中的擂煞,在調(diào)試時也需要源文件』烀郑現(xiàn)在把源代碼恢復原樣,我們繼續(xù)調(diào)試对省。首先用start命令開始執(zhí)行程序:

$ gdb main...

(gdb) start

Breakpoint 1 at 0x80483ad: file main.c, line 14.

Starting program: /home/akaedu/main main () at main.c:14

14 result[0] = add_range(1, 10);

(gdb)

gdb停在main函數(shù)中變量定義之后的第一條語句處等待我們發(fā)命令蝗拿,gdb列出的這條語句是即將執(zhí)行的下一條語句。我們可以用next命令(簡寫為n)控制這些語句一條一條地執(zhí)行:

(gdb) n

15 result[1] = add_range(1, 100);

(gdb) (直接回車)

16 printf("result[0]=%d\nresult[1]=%d\n", result[0], result[1]);

(gdb) (直接回車)

result[0]=55

result[1]=5105

17 return 0;

用n命令依次執(zhí)行兩行賦值語句和一行打印語句蒿涎,在執(zhí)行打印語句時結(jié)果立刻打出來了哀托,然后停在return語句之前等待我們發(fā)命令。雖然我們完全控制了程序的執(zhí)行劳秋,但仍然看不出哪里錯了仓手,因為錯誤不在main函數(shù)中而在add_range函數(shù)中胖齐,現(xiàn)在用start命令重新來過,這次用step命令(簡寫為s)鉆進add_range函數(shù)中去跟蹤執(zhí)行:

(gdb) start

The program being debugged has been started already.

Start it from the beginning? (y or n) y

Breakpoint 2 at 0x80483ad: file main.c, line 14.

Starting program: /home/akaedu/main

main () at main.c:14

14 result[0] = add_range(1, 10);

(gdb) sadd_range (low=1, high=10) at main.c:6

6 for (i = low; i <= high; i++)

這次停在了add_range函數(shù)中變量定義之后的第一條語句處俗或。在函數(shù)中有幾種查看狀態(tài)的辦法市怎,backtrace命令(簡寫為bt)可以查看函數(shù)調(diào)用的棧幀:

(gdb) bt

#0? add_range (low=1, high=10) at main.c:6

#1? 0x080483c1 in main () at main.c:14

可見當前的add_range函數(shù)是被main函數(shù)調(diào)用的,main傳進來的參數(shù)是low=1, high=10辛慰。main函數(shù)的棧幀編號為1区匠,add_range的棧幀編號為0。現(xiàn)在可以用info命令(簡寫為i)查看add_range函數(shù)局部變量的值:

(gdb) i locals

i = 0

sum = 0

如果想查看main函數(shù)當前局部變量的值也可以做到帅腌,先用frame命令(簡寫為f)選擇1號棧幀然后再查看局部變量:

(gdb) f 1

#1? 0x080483c1 in main () at main.c:14

14 result[0] = add_range(1, 10);

(gdb) i locals

result = {0, 0, 0, 0, 0, 0, 134513196, 225011984, -1208685768, -1081160480, ...?

-1208623680}

注意到result數(shù)組中有很多元素具有雜亂無章的值驰弄,我們知道未經(jīng)初始化的局部變量具有不確定的值。到目前為止一切正常速客。用s或n往下走幾步戚篙,然后用print命令(簡寫為p)打印出變量sum的值:

(gdb) s

7 sum = sum + i;

(gdb) (直接回車)

6 for (i = low; i <= high; i++)

(gdb) (直接回車)

7 sum = sum + i;

(gdb) (直接回車)

6 for (i = low; i <= high; i++)

(gdb) p sum

$1 = 3

第一次循環(huán)i是1,第二次循環(huán)i是2溺职,加起來是3岔擂,沒錯。這里的$1表示gdb保存著這些中間結(jié)果浪耘,$后面的編號會自動增長乱灵,在命令中可以用$1、$2七冲、$3等編號代替相應的值痛倚。由于我們本來就知道第一次調(diào)用的結(jié)果是正確的,再往下跟也沒意義了澜躺,可以用finish命令讓程序一直運行到從當前函數(shù)返回為止:

(gdb) finish

Run till exit from #0? add_range (low=1, high=10) at main.c:6

0x080483c1 in main () at main.c:14

14 result[0] = add_range(1, 10);

Value returned is $2 = 55返回值是55蝉稳,當前正準備執(zhí)行賦值操作,用s命令賦值掘鄙,然后查看result數(shù)組:

(gdb) s

15 result[1] = add_range(1, 100);

(gdb) p result

$3 = {55, 0, 0, 0, 0, 0, 134513196, 225011984, -1208685768, -1081160480, ...? -1208623680}

第一個值55確實賦給了result數(shù)組的第0個元素耘戚。下面用s命令進入第二次add_range調(diào)用,進入之后首先查看參數(shù)和局部變量:

(gdb) s

add_range (low=1, high=100) at main.c:6

6 for (i = low; i <= high; i++)

(gdb) bt

#0? add_range (low=1, high=100) at main.c:6

#1? 0x080483db in main () at main.c:15

(gdb) i locals

i = 11

sum = 55

由于局部變量i和sum沒初始化操漠,所以具有不確定的值毕莱,又由于兩次調(diào)用是挨著的,i和sum正好取了上次調(diào)用時的值颅夺,原來這跟例 3.7 “驗證局部變量存儲空間的分配和釋放”是一樣的道理,只不過我這次舉的例子設法讓局部變量sum在第一次調(diào)用時初值為0了蛹稍。i的初值不是0倒沒關(guān)系吧黄,在for循環(huán)中會賦值為0的,但sum如果初值不是0唆姐,累加得到的結(jié)果就錯了拗慨。好了,我們已經(jīng)找到錯誤原因,可以退出gdb修改源代碼了赵抢。如果我們不想浪費這次調(diào)試機會剧蹂,可以在gdb中馬上把sum的初值改為0繼續(xù)運行,看看這一處改了之后還有沒有別的Bug:

(gdb) set var sum=0

(gdb) finish

Run till exit from #0? add_range (low=1, high=100) at main.c:6

0x080483db in main () at main.c:15

15 result[1] = add_range(1, 100);

Value returned is $4 = 5050

(gdb) n

16 printf("result[0]=%d\nresult[1]=%d\n", result[0], result[1]);

(gdb) (直接回車)

result[0]=55

result[1]=5050

17 return 0;

這樣結(jié)果就對了烦却。修改變量的值除了用set命令之外也可以用print命令宠叼,因為print命令后面跟的是表達式,而我們知道賦值和函數(shù)調(diào)用也都是表達式其爵,所以也可以用print命令修改變量的值或者調(diào)用函數(shù):

(gdb) p result[2]=33

$5 = 33

(gdb) p printf("result[2]=%d\n", result[2])

result[2]=33

$6 = 13

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子维蒙,更是在濱河造成了極大的恐慌错蝴,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,817評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件摇幻,死亡現(xiàn)場離奇詭異横侦,居然都是意外死亡,警方通過查閱死者的電腦和手機绰姻,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,329評論 3 385
  • 文/潘曉璐 我一進店門枉侧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人龙宏,你說我怎么就攤上這事棵逊。” “怎么了银酗?”我有些...
    開封第一講書人閱讀 157,354評論 0 348
  • 文/不壞的土叔 我叫張陵辆影,是天一觀的道長。 經(jīng)常有香客問我黍特,道長蛙讥,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,498評論 1 284
  • 正文 為了忘掉前任灭衷,我火速辦了婚禮次慢,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘翔曲。我一直安慰自己迫像,他們只是感情好,可當我...
    茶點故事閱讀 65,600評論 6 386
  • 文/花漫 我一把揭開白布瞳遍。 她就那樣靜靜地躺著闻妓,像睡著了一般。 火紅的嫁衣襯著肌膚如雪掠械。 梳的紋絲不亂的頭發(fā)上由缆,一...
    開封第一講書人閱讀 49,829評論 1 290
  • 那天注祖,我揣著相機與錄音,去河邊找鬼均唉。 笑死是晨,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的舔箭。 我是一名探鬼主播罩缴,決...
    沈念sama閱讀 38,979評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼限嫌!你這毒婦竟也來了靴庆?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,722評論 0 266
  • 序言:老撾萬榮一對情侶失蹤怒医,失蹤者是張志新(化名)和其女友劉穎炉抒,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體稚叹,經(jīng)...
    沈念sama閱讀 44,189評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡焰薄,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,519評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了扒袖。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片塞茅。...
    茶點故事閱讀 38,654評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖季率,靈堂內(nèi)的尸體忽然破棺而出野瘦,到底是詐尸還是另有隱情,我是刑警寧澤飒泻,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布鞭光,位于F島的核電站,受9級特大地震影響泞遗,放射性物質(zhì)發(fā)生泄漏惰许。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,940評論 3 313
  • 文/蒙蒙 一史辙、第九天 我趴在偏房一處隱蔽的房頂上張望汹买。 院中可真熱鬧,春花似錦聊倔、人聲如沸晦毙。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,762評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽结序。三九已至,卻和暖如春纵潦,著一層夾襖步出監(jiān)牢的瞬間徐鹤,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,993評論 1 266
  • 我被黑心中介騙來泰國打工邀层, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留返敬,地道東北人。 一個月前我還...
    沈念sama閱讀 46,382評論 2 360
  • 正文 我出身青樓寥院,卻偏偏與公主長得像劲赠,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子秸谢,可洞房花燭夜當晚...
    茶點故事閱讀 43,543評論 2 349

推薦閱讀更多精彩內(nèi)容

  • 即使經(jīng)驗非常豐富的程序員凛澎,在編寫程序的時候也避免不了出錯。程序中的語法錯誤通彻捞悖可以在翻譯階段就能被診斷出來塑煎,但邏輯...
    紅色海_閱讀 1,924評論 1 0
  • 程序調(diào)試的基本思想是“分析現(xiàn)象->假設錯誤原因->產(chǎn)生新的現(xiàn)象去驗證假設”這樣一個循環(huán)過程,根據(jù)現(xiàn)象如何假設錯誤原...
    Manfred_Zone閱讀 16,508評論 0 26
  • ns3進入gdb./waf --run "scratch/first" --command-template="g...
    岳麓山雞王閱讀 585評論 0 0
  • 調(diào)試前準備 獲取進程的內(nèi)核轉(zhuǎn)儲(core dump) why:最大好處是臭蚁,其保存了問題發(fā)生時的狀態(tài)最铁。記錄進程當前狀...
    Gitlusen閱讀 920評論 0 2
  • gdb是linux操作系統(tǒng)特有的調(diào)試工具冷尉,可以完成一般IDE提供的所有調(diào)試功能。使用gdb調(diào)試程序之前系枪,必須使用g...
    zhile_doing閱讀 3,251評論 0 2