做網(wǎng)站做小時(shí)seo加盟
在VS里面調(diào)試很方便對(duì)吧?(F5直接調(diào)試,F10逐過(guò)程調(diào)試--不進(jìn)函數(shù),F11逐語(yǔ)句調(diào)試--進(jìn)函數(shù),F9創(chuàng)建斷點(diǎn)),那在Linux中怎么調(diào)試呢?
我們需要用到一個(gè)工具:gdb
我們知道VS中程序的版本大致有兩種模式:debug(開發(fā)模式,可被調(diào)試)和release(發(fā)布模式,不可被調(diào)試),為什么會(huì)形成這樣的差異呢?其實(shí)在編譯器形成可執(zhí)行程序的時(shí)候,會(huì)給可執(zhí)行程序添加調(diào)試信息,gcc編譯的時(shí)候默認(rèn)生成的是release版本,這樣實(shí)現(xiàn)gcc/g++使用debug模式編譯(makefile):
processbar-debug:Main.c Processbar.cgcc -o $@ $^ -g.PHONY:clean
clean:rm -f processbar-debug
debug和release版本的不同可以看出:
debug確實(shí)比release版本大了很多(11936-8792=3144)?debug版本是新增調(diào)試信息,debug版本的肯定比release版本的占用空間大(確實(shí)如此則證明新增數(shù)據(jù))
那為什么要存在這樣的差異呢?
其實(shí)是因?yàn)槭褂媒巧牟町?#xff0c;用戶是用戶,程序員是程序員,用戶是程序的使用者,他不需要知道如何調(diào)試,只要會(huì)用就好了,多放調(diào)試信息還浪費(fèi)空間,但是程序員是開發(fā)者,必須要知道調(diào)試信息以供調(diào)試,否則開發(fā)受阻,bug很難de出來(lái)(在公司,產(chǎn)品經(jīng)理==用戶,有的時(shí)候產(chǎn)品經(jīng)理就很抽象,假用戶威給程序組沒事找事,我要diss這類產(chǎn)品經(jīng)理)
可以這樣來(lái)查看debug版本下的調(diào)試信息:
readelf -S processbar-debug
?.rodata:只讀區(qū)
.text:代碼區(qū)
.data:數(shù)據(jù)區(qū)
.bss:未初始化全局?jǐn)?shù)據(jù)區(qū)
debug信息:?
readelf -S processbar-debug | grep -i debug
下面簡(jiǎn)單介紹gdb的使用
使用前先安裝下:
yum install -y gdb
所以想要使用就直接gdb+可執(zhí)行程序名稱
gdb processbar-debug
常用命令
quit/q
在進(jìn)入調(diào)試器后想退出可直接quit或者q:
通過(guò)分屏可以看出gdb在使用時(shí)算一個(gè)超絕進(jìn)程:
list/l
list可用于查詢?cè)次募?nèi)容,但是是不支持這樣直接查詢?cè)次募?#xff1a;
list Processbar.c
從第0行開始查:?
list 0
簡(jiǎn)寫效果是一樣的:?
l 0
一查默認(rèn)是查十行,在gdb中是會(huì)記住上次執(zhí)行過(guò)的命令的,所以只需要按回車就可以查詢整個(gè)文件了:
????
?也可以這樣查:
l Processbar.c:0
還可以查詢某個(gè)具體函數(shù):
l Processbar.c:ProcBar
?在查詢某行的時(shí)候并不是從它開始,而是顯示上下文:
l 15
run/r
直接r相當(dāng)于VS中的F5,直接執(zhí)行不調(diào)試?
break/b
直接執(zhí)行需要配合斷點(diǎn)一起使用,break/b就是打斷點(diǎn)
b x //x是行號(hào)
斷點(diǎn)只能一個(gè)一個(gè)打?
可以指明給某個(gè)文件:
b Processbar.c:20
還可以直接給某個(gè)函數(shù)打斷點(diǎn):
b main
這樣打出來(lái)的斷點(diǎn)是位于函數(shù)的第一條語(yǔ)句處的?
與在VS中的打斷點(diǎn)作比較:?
?打過(guò)斷點(diǎn)的地方可以看出有紅點(diǎn),那gdb中怎么查看打過(guò)的斷點(diǎn)呢?
可以使用這條命令(info break):
info b
?
i b
?
?Enb:斷點(diǎn)的使能:有/沒有
delete/d
在打斷點(diǎn)的時(shí)候通過(guò)文件名+行號(hào)打,但是刪除的時(shí)候不可以通過(guò)這種方式刪除
?
?通過(guò)加編號(hào)的方式刪除斷點(diǎn):
d x //x為號(hào)碼
?斷點(diǎn)編號(hào)也是線性增長(zhǎng)的
disable/enable
在VS中可以實(shí)現(xiàn)禁用斷點(diǎn)的功能:
可以通過(guò)disable來(lái)禁用斷點(diǎn):
disable x //x為斷點(diǎn)編號(hào)
?斷點(diǎn)有但無(wú)用:
1.被禁用
2.為空行
可以通過(guò)enable命令來(lái)開啟禁用的斷點(diǎn):
enable x //x為斷點(diǎn)編號(hào)
next/n
逐過(guò)程:F10
即遇到函數(shù)不進(jìn)入函數(shù)調(diào)試
step/s
逐語(yǔ)句 :F11
遇到函數(shù)進(jìn)入函數(shù),進(jìn)行逐語(yǔ)句調(diào)試
print/p?
在VS中調(diào)試是想要看到某些變量的變化過(guò)程
在gdb中可以這樣來(lái)查看變量的變化過(guò)程:
p x //x為變量名
地址也可以查哦:
p &i //i為變量名
?但是這樣查看又太麻煩了,太原始了哇!!!
?display/undisplay
display可以常顯示變量
undisplay可以把當(dāng)前常顯示的內(nèi)容去掉
undisplay x //x為變量編號(hào)
finish
finish是運(yùn)行結(jié)束所在函數(shù)就停止?
until
?在調(diào)試時(shí)可能出現(xiàn)的情況還有比如任意跳轉(zhuǎn)到函數(shù)的某一行處(中間代碼都運(yùn)行了)
until x //x為行號(hào)
info
?info b是查看斷點(diǎn)的情況,info locals則可用于查看當(dāng)前棧幀局部變量的值
info locals
i locals
set var
set var可用于修改變量的值
set var i=100 //將i的值變?yōu)?00
區(qū)域化執(zhí)行?
?調(diào)試工具的核心作用是幫助你找問(wèn)題,具體的解決需要人為,如果已經(jīng)定位到問(wèn)題所在行,那就不需要進(jìn)行調(diào)試了,調(diào)試是為了幫助我們避免進(jìn)行干瞪眼這種費(fèi)時(shí)費(fèi)力的調(diào)試方法誕生的,如果一份代碼幾萬(wàn)行,從頭盯到尾是很費(fèi)時(shí)費(fèi)力的,我們希望它做的是區(qū)域化執(zhí)行
因?yàn)橛袛帱c(diǎn)的存在,我們就可以通過(guò)斷點(diǎn)實(shí)現(xiàn)區(qū)域化執(zhí)行,從一個(gè)斷點(diǎn)運(yùn)行到下一個(gè)斷點(diǎn)處,按范圍去打斷點(diǎn)就可以實(shí)現(xiàn)按范圍查找,二分打可快速縮小范圍