C++ gdb調試

cmake和gdb調試程序

因爲出發點是想要在cmake後使用gdb,所以先寫一下cmake和gdb的簡單的一個流程,此部分轉自:WELENhtml

1.  cmake支持gdb的實現,
首先在CMakeLists.txt下加入
SET(CMAKE_BUILD_TYPE "Debug") 
在下面加入:
SET(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g -ggdb")
SET(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -Wall")
緣由是CMake 中有一個變量 CMAKE_BUILD_TYPE ,能夠的取值是 Debug Release RelWithDebInfo >和 MinSizeRel。
當這個變量值爲 Debug 的時候,CMake 會使用變量 CMAKE_CXX_FLAGS_DEBUG 和 CMAKE_C_FLAGS_DEBUG 中的字符串做爲編譯選項生成 Makefile;


2.  在GDB中間加入程序啓動參數
好比咱們須要調試一個可執行文件./a.out help
這時
$gdb ./a.out
進入到gdb的命令行模式下,而後:
(gdb) set args help
就能加上可執行文件須要的參數,若是要看argc[1]到argc[N]的參數,只須要
(gdb) show args

3. gdb中查看字符串,地址的操做,數據類型
比始有一個int型的變量i,相要知道他的相關信息,能夠
(gdb) print i
打印出變量i的當前值
(gdb)x &i
與上面的命令等價。

若是有x命令看時,須要看一片內存區域,(若是某個地方的值爲0,用x時會自動截斷了)
(gdb) x/16bx address
單字節16進制打印address地址處的長度爲16的空間的內存,16表示空間長度,不是16進制,x表示16進制,b表示byte單字節

gdb看變量是哪一個數據類型 
(gdb) whatis i
便可知道i是什麼類型的變量linux

 gdb調試利器

接下來介紹一下gdb自己以及一些經常使用的指令,轉自: Linux Tools Quick Tutorialc++

GDB是一個由GNU開源組織發佈的、UNIX/LINUX操做系統下的、基於命令行的、功能強大的程序調試工具。 對於一名Linux下工做的c++程序員,gdb是必不可少的工具;程序員

1. 啓動gdb

對C/C++程序的調試,須要在編譯前就加上-g選項:shell

$g++ -g hello.cpp -o hello

調試可執行文件:express

$gdb <program>

program也就是你的執行文件,通常在當前目錄下。數組

調試core文件(core是程序非法執行後core dump後產生的文件):bash

$gdb <program> <core dump file>
$gdb program core.11127

調試服務程序:數據結構

$gdb <program> <PID>
$gdb hello 11127

若是你的程序是一個服務程序,那麼你能夠指定這個服務程序運行時的進程ID。gdb會自動attach上去,並調試他。program應該在PATH環境變量中搜索獲得。多線程

2. gdb交互命令

啓動gdb後,進入到交互模式,經過如下命令完成對程序的調試;注意高頻使用的命令通常都會有縮寫,熟練使用這些縮寫命令能提升調試的效率;

運行

  • run:簡記爲 r ,其做用是運行程序,當遇到斷點後,程序會在斷點處中止運行,等待用戶輸入下一步的命令。
  • continue (簡寫c ):繼續執行,到下一個斷點處(或運行結束)
  • next:(簡寫 n),單步跟蹤程序,當遇到函數調用時,也不進入此函數體;此命令同 step 的主要區別是,step 遇到用戶自定義的函數,將步進到函數中去運行,而 next 則直接調用函數,不會進入到函數體內。
  • step (簡寫s):單步調試若是有函數調用,則進入函數;與命令n不一樣,n是不進入調用的函數的
  • until:當你厭倦了在一個循環體內單步跟蹤時,這個命令能夠運行程序直到退出循環體。
  • until+行號: 運行至某行,不只僅用來跳出循環
  • finish: 運行程序,直到當前函數完成返回,並打印函數返回時的堆棧地址和返回值及參數值等信息。
  • call 函數(參數):調用程序中可見的函數,並傳遞「參數」,如:call gdb_test(55)
  • quit:簡記爲 q ,退出gdb

設置斷點

  • break n (簡寫b n):在第n行處設置斷點
    (能夠帶上代碼路徑和代碼名稱: b OAGUPDATE.cpp:578)
  • b fn1 if a>b:條件斷點設置
  • break func(break縮寫爲b):在函數func()的入口處設置斷點,如:break cb_button
  • delete 斷點號n:刪除第n個斷點
  • disable 斷點號n:暫停第n個斷點
  • enable 斷點號n:開啓第n個斷點
  • clear 行號n:清除第n行的斷點
  • info b (info breakpoints) :顯示當前程序的斷點設置狀況
  • delete breakpoints:清除全部斷點:

查看源代碼

  • list :簡記爲 l ,其做用就是列出程序的源代碼,默認每次顯示10行。
  • list 行號:將顯示當前文件以「行號」爲中心的先後10行代碼,如:list 12
  • list 函數名:將顯示「函數名」所在函數的源代碼,如:list main
  • list :不帶參數,將接着上一次 list 命令的,輸出下邊的內容。

打印表達式

  • print 表達式:簡記爲 p ,其中「表達式」能夠是任何當前正在被測試程序的有效表達式,好比當前正在調試C語言的程序,那麼「表達式」能夠是任何C語言的有效表達式,包括數字,變量甚至是函數調用。
  • print a:將顯示整數 a 的值
  • print ++a:將把 a 中的值加1,並顯示出來
  • print name:將顯示字符串 name 的值
  • print gdb_test(22):將以整數22做爲參數調用 gdb_test() 函數
  • print gdb_test(a):將以變量 a 做爲參數調用 gdb_test() 函數
  • display 表達式:在單步運行時將很是有用,使用display命令設置一個表達式後,它將在每次單步進行指令後,緊接着輸出被設置的表達式及值。如: display a
  • watch 表達式:設置一個監視點,一旦被監視的「表達式」的值改變,gdb將強行終止正在被調試的程序。如: watch a
  • whatis :查詢變量或函數
  • info function: 查詢函數
  • 擴展info locals: 顯示當前堆棧頁的全部變量

查詢運行信息

  • where/bt :當前運行的堆棧列表;
  • bt backtrace 顯示當前調用堆棧
  • up/down 改變堆棧顯示的深度
  • set args 參數:指定運行時的參數
  • show args:查看設置好的參數
  • info program: 來查看程序的是否在運行,進程號,被暫停的緣由。

分割窗口

  • layout:用於分割窗口,能夠一邊查看代碼,一邊測試:
  • layout src:顯示源代碼窗口
  • layout asm:顯示反彙編窗口
  • layout regs:顯示源代碼/反彙編和CPU寄存器窗口
  • layout split:顯示源代碼和反彙編窗口
  • Ctrl + L:刷新窗口

註解

交互模式下直接回車的做用是重複上一指令,對於單步調試很是方便;

3. 更強大的工具

cgdb

cgdb能夠看做gdb的界面加強版,用來替代gdb的 gdb -tui。cgdb主要功能是在調試時進行代碼的同步顯示,這無疑增長了調試的方便性,提升了調試效率。界面相似vi,符合unix/linux下開發人員習慣;若是熟悉gdb和vi,幾乎能夠當即使用cgdb。

 

基礎用法

接下來來一個更詳細的介紹和使用方法,轉自:大頭雨山

1. 簡介

GDB(GNU Debugger)是GCC的調試工具。其功能強大,現描述以下: 
GDB主要幫忙你完成下面四個方面的功能: 
1.啓動你的程序,能夠按照你的自定義的要求爲所欲爲的運行程序。 
2.可以讓被調試的程序在你所指定的調置的斷點處停住。(斷點能夠是條件表達式) 
3.當程序被停住時,能夠檢查此時你的程序中所發生的事。 
4.動態的改變你程序的執行環境。

2 生成調試信息

通常來講GDB主要調試的是C/C++的程序。要調試C/C++的程序,首先在編譯時,咱們必需要把調試信息加到可執行文件中。使用編譯器(cc/gcc/g++)的 -g 參數能夠作到這一點。如:

gcc -g hello.c -o hello g++ -g hello.cpp -o hello
  • 1
  • 2
  • 1
  • 2
  • 1
  • 2

若是沒有-g,你將看不見程序的函數名、變量名,所代替的全是運行時的內存地址。當你用-g把調試信息加入以後,併成功編譯目標代碼之後,讓咱們來看看如何用gdb來調試他。

3 啓動GDB 的方法

一、gdb program

program 也就是你的執行文件,通常在當前目錄下。

二、gdb program core

用gdb同時調試一個運行程序和core文件,core是程序非法執行後core dump後產生的文件。

三、gdb program 1234

若是你的程序是一個服務程序,那麼你能夠指定這個服務程序運行時的進程ID。gdb會自動attach上去,並調試他。program應該在PATH環境變量中搜索獲得。

4 程序運行上下文

4.1 程序運行參數

set args 可指定運行時參數。(如:set args 10 20 30 40 50 ) 
show args 命令能夠查看設置好的運行參數。 
run (r) 啓動程序 
不指定運行參數 r 
指定運行參數r 10 20 30 40 50

4.2 工做目錄

cd 至關於shell的cd命令。 
pwd 顯示當前的所在目錄。

4.3 程序的輸入輸出

info terminal顯示你程序用到的終端的模式。 
使用重定向控制程序輸出。如:run > outfile 
tty命令能夠設置輸入輸出使用的終端設備。如:tty /dev/tty1

5 設置斷點

5.1 簡單斷點

break 設置斷點,能夠簡寫爲b 
b 10設置斷點,在源程序第10行 
b func設置斷點,在func函數入口處

5.2 多文件設置斷點

在進入指定函數時停住: 
C++中可使用 
class::function或function(type,type)格式來指定函數名。若是有名稱空間,可使用namespace::class::function或者function(type,type)格式來指定函數名。 
break filename:linenum 
在源文件filenamelinenum行處停住 
break filename:function 
在源文件filenamefunction函數的入口處停住 
break class::functionfunction(type,type) 
在類class的function函數的入口處停住 
break namespace::class::function 
在名稱空間爲namespace的類class的function函數的入口處停住

5.3 查詢全部斷點

info b

6 觀察點

watch 爲表達式(變量)expr設置一個觀察點。當表達式值有變化時,立刻停住程序。 
rwatch表達式(變量)expr被讀時,停住程序。 
awatch 表達式(變量)的值被讀或被寫時,停住程序。 
info watchpoints列出當前所設置了的全部觀察點。

7 條件斷點

通常來講,爲斷點設置一個條件,咱們使用if關鍵詞,後面跟其斷點條件。而且,條件設置好後,咱們能夠用condition命令來修改斷點的條件。而且,條件設置好後,咱們能夠用condition命令來修改斷點的條件。(只有break 和 watch命令支持if,catch目前暫不支持if)。 
設置一個條件斷點 
b test.c:8 if intValue == 5 
condition 與break if相似,只是condition只能用在已存在的斷點上 
修改斷點號爲bnum的中止條件爲expression 
condition bnum expression 
清楚斷點號爲bnum的中止條件 
condition bnum 
ignore 忽略中止條件幾回 
表示忽略斷點號爲bnum的中止條件count次 
Ignore bnum count

8 維護中止點

  1. clear清除全部的已定義的中止點。
  2. clear function清除全部設置在函數上的中止點。
  3. clear linenum清除全部設置在指定行上的中止點。
  4. clear filename:linenum清除全部設置在指定文件:指定行上的中止點。
  5. delete [breakpoints] [range...]刪除指定的斷點,breakpoints爲斷點號。若是不指定斷點號,則表示刪除全部的斷點。range表示斷點號的範圍(如:3-7)。其簡寫命令爲d。
  6. 比刪除更好的一種方法是disable中止點,disable了的中止點,GDB不會刪除,當你還須要時,enable便可,就好像回收站同樣。
  7. disable [breakpoints] [range...] disable所指定的中止點,breakpoints爲中止點號。若是什麼都不指定,表示disable全部的中止點。簡寫命令是dis.
  8. enable [breakpoints] [range...]enable所指定的中止點,breakpoints爲中止點號。
  9. enable [breakpoints] once range…enable所指定的中止點一次,當程序中止後,該中止點立刻被GDB自動disable。
  10. enable [breakpoints] delete range…enable所指定的中止點一次,當程序中止後,該中止點立刻被GDB自動刪除。

9 爲中止點設定運行命令

咱們可使用GDB提供的command命令來設置中止點的運行命令。也就是說,當運行的程序在被中止住時,咱們可讓其自動運行一些別的命令,這頗有利行自動化調試。對基於GDB的自動化調試是一個強大的支持。

1 commands [bnum]
2 … command-list …
3 end

爲斷點號bnum指寫一個命令列表。當程序被該斷點停住時,gdb會依次運行命令列表中的命令。 
例如:

1 break foo if x>0
2 commands
3 printf 「x is %d 「,x
4 continue
5 end

斷點設置在函數foo中,斷點條件是x>0,若是程序被斷住後,也就是,一旦x的值在foo函數中大於0,GDB會自動打印出x的值,並繼續運行程序。 

若是你要清除斷點上的命令序列,那麼只要簡單的執行一下commands命令,並直接在打個end就好了。

10 調試代碼

  1. run 運行程序,可簡寫爲r
  2. next 單步跟蹤,函數調用看成一條簡單語句執行,可簡寫爲n
  3. step 單步跟蹤,函數調進入被調用函數體內,可簡寫爲s
  4. finish 退出函數
  5. until 在一個循環體內單步跟蹤時,這個命令能夠運行程序直到退出循環體,可簡寫爲u。
  6. continue 繼續運行程序,可簡寫爲c
  7. stepisinextini 單步跟蹤一條機器指令,一條程序代碼有可能由數條機器指令完成,stepi和nexti能夠單步執行機器指令。
  8. info program 來查看程序的是否在運行,進程號,被暫停的緣由。

11 查看運行時數據

  1. print 打印變量、字符串、表達式等的值,可簡寫爲p
  2. p count 打印count的值
  3. p cou1+cou2+cou3 打印表達式值
  4. print接受一個表達式,GDB會根據當前的程序運行的數據來計算這個表達式,表達式能夠是當前程序運行中的const常量、變量、函數等內容。可是GDB不能使用程序中定義的宏。

12 程序變量

在GDB中,你能夠隨時查看如下三種變量的值: 
1. 全局變量(全部文件可見的) 
2. 靜態全局變量(當前文件可見的) 
3. 局部變量(當前Scope可見的) 
若是你的局部變量和全局變量發生衝突(也就是重名),通常狀況下是局部變量會隱藏全局變量,也就是說,若是一個全局變量和一個函數中的局部變量同名時,若是當前中止點在函數中,用print顯示出的變量的值會是函數中的局部變量的值。若是此時你想查看全局變量的值時,你可使用「::」操做符: 
file::variable 
function::variable 
能夠經過這種形式指定你所想查看的變量,是哪一個文件中的或是哪一個函數中的。例如,查看文件f2.c中的全局變量x的值:

1 p ‘f2.c’::x

固然,「::」操做符會和C++中的發生衝突,GDB能自動識別「::」是否C++的操做符,因此你沒必要擔憂在調試C++程序時會出現異常。 
4. 數組變量 
有時候,你須要查看一段連續的內存空間的值。好比數組的一段,或是動態分配的數據的大小。你可使用GDB的「@」操做符,「@」的左邊是第一個內存的地址的值,「@」的右邊則你你想查看內存的長度。例如,你的程序中有這樣的語句:

1 int *array = (int *) malloc (len * sizeof (int));

因而,在GDB調試過程當中,你能夠以以下命令顯示出這個動態數組的取值:

1 p *array@len

@的左邊是數組的首地址的值,也就是變量array所指向的內容,右邊則是數據的長度,其保存在變量len中。

13 自動顯示

你能夠設置一些自動顯示的變量,當程序停住時,或是在你單步跟蹤時,這些變量會自動顯示。相關的GDB命令是display。

1 display expr
2 display/fmt expr
3 display/fmt addr

expr是一個表達式,fmt表示顯示的格式,addr表示內存地址,當你用display設定好了一個或多個表達式後,只要你的程序被停下來,GDB會自動顯示你所設置的這些表達式的值。

1 info display

查看display設置的自動顯示的信息。

1 undisplay dnums…
2 delete display dnums…

刪除自動顯示,dnums意爲所設置好了的自動顯式的編號。若是要同時刪除幾個,編號能夠用空格分隔,若是要刪除一個範圍內的編號,能夠用減號表示(如:2-5)

1 disable display dnums…
2 enable display dnums…

disable和enalbe不刪除自動顯示的設置,而只是讓其失效和恢復。

14 歷史記錄

當你用GDB的print查看程序運行時的數據時,你每個print都會被GDB記錄下來。GDB會以2, 1。這個功能所帶來的好處是,若是你先前輸入了一個比較長的表達式,若是你還想查看這個表達式的值,你可使用歷史記錄來訪問,省去了重複輸入。

 1 (gdb)show values
 2 Print the last ten values in the value history, with their item numbers. This is
 3 like ‘p $$9’ repeated ten times, except that show values does not change the
 4 history.
 5 
 6 (gdb)show values n
 7 Print ten history values centered on history item number n.
 8 
 9 (gdb)show values +
10 Print ten history values just after the values last printed. If no more values are
11 available, show values + produces no display.

15 改變程序的執行

一旦使用GDB掛上被調試程序,當程序運行起來後,你能夠根據本身的調試思路來動態地在GDB中更改當前被調試程序的運行線路或是其變量的值,這個強大的功能可以讓你更好的調試你的程序,好比,你能夠在程序的一次運行中走遍程序的全部分支。

15.1 修改變量值

修改被調試程序運行時的變量值,在GDB中很容易實現,使用GDB的print命令便可完成。如:

1 (gdb) print x=4

x=4這個表達式是C/C++的語法,意爲把變量x的值修改成4,若是你當前調試的語言是Pascal,那麼你可使用Pascal的語法:x:=4。 
在某些時候,頗有可能你的變量和GDB中的參數衝突,如:

1 (gdb) whatis width
2 type = double
3 (gdb) p width
4 $4 = 13
5 (gdb) set width=47
6 Invalid syntax in expression.

由於,set width是GDB的命令,因此,出現了「Invalid syntax in expression」的設置錯誤,此時,你可使用set var命令來告訴GDB,width不是你GDB的參數,而是程序的變量名,如:

1 (gdb) set var width=47

另外,還可能有些狀況,GDB並不報告這種錯誤,因此保險起見,在你改變程序變量取值時,最好都使用set var格式的GDB命令。

15.2 跳轉執行

通常來講,被調試程序會按照程序代碼的運行順序依次執行。GDB提供了亂序執行的功能,也就是說,GDB能夠修改程序的執行順序,可讓程序執行隨意跳躍。這個功能能夠由GDB的jump命令來完:

1 jump linespec

指定下一條語句的運行點。能夠是文件的行號,能夠是file:line格式,能夠是+num這種偏移量格式。表示下一條運行語句從哪裏開始。

1 jump *address

這裏的是代碼行的內存地址。 
注意,jump命令不會改變當前的程序棧中的內容,因此,當你從一個函數跳到另外一個函數時,當函數運行完返回時進行彈棧操做時必然會發生錯誤,可能結果仍是很是奇怪的,甚至於產生程序Core Dump。因此最好是同一個函數中進行跳轉。 
熟悉彙編的人都知道,程序運行時,eip寄存器用於保存當前代碼所在的內存地址。因此,jump命令也就是改變了這個寄存器中的值。因而,你可使用「set $pc」來更改跳轉執行的地址。如:

1 set $pc = 0×485

15.3 產生信號量

使用singal命令,能夠產生一個信號量給被調試的程序。如:中斷信號Ctrl+C。這很是方便於程序的調試,能夠在程序運行的任意位置設置斷點,並在該斷點用GDB產生一個信號量,這種精確地在某處產生信號很是有利程序的調試。 
語法是:

1 signal signal

UNIX的系統信號量一般從1到15。因此取值也在這個範圍。 
single命令和shell的kill命令不一樣,系統的kill命令發信號給被調試程序時,是由GDB截獲的,而single命令所發出一信號則是直接發給被調試程序的。

15.4 強制函數返回

若是你的調試斷點在某個函數中,並還有語句沒有執行完。你可使用return命令強制函數忽略尚未執行的語句並返回。

1 return
2 return expression

使用return命令取消當前函數的執行,並當即返回,若是指定了,那麼該表達式的值會被認做函數的返回值。

15.5 強制調用函數

1 call expr

表達式中能夠一是函數,以此達到強制調用函數的目的。並顯示函數的返回值,若是函數返回值是void,那麼就不顯示。

1 print expr

另外一個類似的命令也能夠完成這一功能——print,print後面能夠跟表達式,因此也能夠用他來調用函數,print和call的不一樣是,若是函數返回void,call則不顯示,print則顯示函數返回值,並把該值存入歷史數據中。

16 顯示源代碼

GDB 能夠打印出所調試程序的源代碼,固然,在程序編譯時必定要加上 –g 的參數,把源程序信息編譯到執行文件中。否則就看不到源程序了。當程序停下來之後, GDB會報告程序停在了那個文件的第幾行上。你能夠用list命令來打印程序的源代碼。默認打印10行,仍是來看一看查看源代碼的GDB命令吧。

1 (gdb)list linenum
2 Print lines centered around line number linenum in the current source file.
3 (gdb)list function

顯示函數名爲function的函數的源程序。

1 list

顯示當前行後面的源程序。

1 list -

顯示當前行前面的源程序。 
通常是打印當前行的上5行和下5行,若是顯示函數是是上2行下8行,默認是10行,固然,你也能夠定製顯示的範圍,使用下面命令能夠設置一次顯示源程序的行數。

1 set listsize count

設置一次顯示源代碼的行數。(unless the list argument explicitly specifies some other number)

1 show listsize
查看當前listsize的設置。

17 調試已運行的進程

兩種方法: 
一、在UNIX下用ps查看正在運行的程序的PID(進程ID),而後用gdb PID process-id 格式掛接正在運行的程序。 
二、先用gdb 關聯上源代碼,並進行gdb,在gdb中用attach process-id 命令來掛接進程的PID。並用detach來取消掛接的進程。

18 線程

若是你程序是多線程的話,你能夠定義你的斷點是否在全部的線程上,或是在某個特定的線程。GDB很容易幫你完成這一工做。

1 break linespec thread threadno
2 break linespec thread threadno if

linespec指定了斷點設置在的源程序的行號。threadno指定了線程的ID,注意,這個ID是GDB分配的,你能夠經過「info threads」命令來查看正在運行程序中的線程信息。若是你不指定‘thread threadno ’則表示你的斷點設在全部線程上面。你還能夠爲某線程指定斷點條件。如:

1 (gdb) break frik.c:13 thread 28 if bartab > lim

當你的程序被GDB停住時,全部的運行線程都會被停住。這方便你你查看運行程序的整體狀況。而在你恢復程序運行時,全部的線程也會被恢復運行。那怕是主進程在被單步調試時。

19 查看棧信息

當程序被停住了,你須要作的第一件事就是查看程序是在哪裏停住的。當你的程序調用了一個函數,函數的地址,函數參數,函數內的局部變量都會被壓入「棧」(Stack)中。你能夠用GDB命令來查看當前的棧中的信息。 
下面是一些查看函數調用棧信息的GDB命令: 
breacktrace,簡稱bt 
打印當前的函數調用棧的全部信息。如:

1 (gdb) bt
2 #0 func (n=250) at tst.c:6
3 #1 0x08048524 in main (argc=1, argv=0xbffff674) at tst.c:30
4 #2 0x400409ed in __libc_start_main () from /lib/libc.so.6

從上能夠看出函數的調用棧信息:__libc_start_main –> main() –> func()

1 backtrace n
2 bt n

n是一個正整數,表示只打印棧頂上n層的棧信息。

1 backtrace -n
2 bt -n

-n表一個負整數,表示只打印棧底下n層的棧信息。

若是你要查看某一層的信息,你須要在切換當前的棧,通常來講,程序中止時,最頂層的棧就是當前棧,若是你要查看棧下面層的詳細信息,首先要作的是切換當前棧。

1 frame n

n是一個從0開始的整數,是棧中的層編號。好比:frame 0,表示棧頂,frame 1,表示棧的第二層。

1 (gdb)frame addr
2 f addr Select the frame at address addr. This is useful mainly if the chaining of stack frames has been damaged by a bug, making it impossible for gdb to assign
3 
4 numbers properly to all frames. In addition, this can be useful when your program has multiple stacks and switches between them.
5 
6 (gdb)up n

表示向棧的上面移動n層,能夠不打n,表示向上移動一層。

1 down n

表示向棧的下面移動n層,能夠不打n,表示向下移動一層。 
上面的命令,都會打印出移動到的棧層的信息。若是你不想讓其打出信息。你可使用這三個命令: 
select-frame 對應於 frame 命令。 
up-silently n 對應於 up 命令。 
down-silently n 對應於 down 命令。 
查看當前棧層的信息,你能夠用如下GDB命令:

1 frame 或 f

會打印出這些信息:棧的層編號,當前的函數名,函數參數值,函數所在文件及行號,函數執行到的語句。

1 info frame
2 info f

20 信號

信號是一種軟中斷,是一種處理異步事件的方法。通常來講,操做系統都支持許多信號。尤爲是UNIX,比較重要應用程序通常都會處理信號。UNIX定義了許多信號,好比SIGINT表示中斷字符信號,也就是Ctrl+C的信號,SIGBUS表示硬件故障的信號;SIGCHLD表示子進程狀態改變信號; SIGKILL表示終止程序運行的信號,等等。

調試程序的時候處理信號:

1 handle signal [keywords...]

signal能夠以SIG開頭或不以SIG開頭,能夠用定義一個要處理信號的範圍(如:SIGIO-SIGKILL,表示處理從 SIGIO信號到SIGKILL的信號,其中包括SIGIO,SIGIOT,SIGKILL三個信號),也可使用關鍵字all來標明要處理全部的信號。一旦被調試的程序接收到信號,運行程序立刻會被GDB停住,以供調試。 
keywords列表以下:

1 nostop

當被調試的程序收到信號時,GDB不會停住程序的運行,但會打出消息告訴你收到這種信號。

1 stop

當被調試的程序收到信號時,GDB會停住你的程序。This implies the print keyword as well.

1 print

當被調試的程序收到信號時,GDB會顯示出一條信息。

1 noprint

當被調試的程序收到信號時,GDB不會告訴你收到信號的信息。This implies the nostop keyword as well.

1 pass
2 noignore

當被調試的程序收到信號時,GDB不處理信號。這表示,GDB會把這個信號交給被調試程序處理 or else it may terminate if the signal is fatal and not handled.

1 nopass
2 ignore

當被調試的程序收到信號時,GDB不會讓被調試程序來處理這個信號。

1 info signals
2 info handle

查看有哪些信號在被GDB檢測中。

21catch

當event發生時,停住程序。event能夠是下面的內容: 
一、throw 一個C++拋出的異常。(throw爲關鍵字) 
二、catch 一個C++捕捉到的異常。(catch爲關鍵字)

22 指定源文件的路徑

某些時候,用-g編譯事後的執行程序中只是包括了源文件的名字,沒有路徑名。GDB提供了可讓你指定源文件的路徑的命令,以便GDB進行搜索。

1 Directory dirname …
2 dir dirname …

加一個源文件路徑到當前路徑的前面。若是你要指定多個路徑,UNIX下你可使用「:」,Windows下你可使用「;」。

1 directory

清除全部的自定義的源文件搜索路徑信息。

show directories

顯示定義了的源文件搜索路徑。

gdb高級用法

一:列文件清單

1.list(l)

1 (gdb)   list   line1,line2

二:執行程序

要想運行準備調試的程序,可以使用run(r)命令,在它後面能夠跟隨發給該程序的任何參數,包括標準輸入和標準輸出說明符(<和>)和外殼通配符(*、?、[、])在內。 
若是你使用不帶參數的run命令,gdb就再次使用你給予前一條run命令的參數,這是頗有用的。 
利用set args命令就能夠修改發送給程序的參數,而使用show args 命令就能夠查看其缺省參數的列表。

1 (gdb)set args –b –x
2 (gdb)show args
3 (gdb)backtrace(bt)  //命令爲堆棧提供向後跟蹤功能。     
4 (gdb)Backtrace       //命令產生一張列表,包含着從最近的過程開始的因此有效過程和調用這些過程的參數。     

三:顯示數據

1. print(p) 命令能夠檢查各個變量的值。

1 (gdb)   print   p   //(p爲變量名)     

2. whatis 命令能夠顯示某個變量的類型

1 (gdb)   whatis   p     
2 type   =   int   *     

print 是gdb的一個功能很強的命令,利用它能夠顯示被調試的語言中任何有效的表達式。表達式除了包含你程序中的變量外,還能夠包含如下內容:

2.1 對程序中函數的調用

1 (gdb)print   find_entry(1,0)     

2.2 數據結構和其餘複雜對象

(gdb)print *table_start $8={e=reference=’\000’,location=0x0,next=0x0} 
  • 1
  • 2
  • 1
  • 2
  • 1
  • 2

2.3 值的歷史成分

(gdb)print $1</span> //(<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">$1爲歷史記錄變量,在之後能夠直接引用 $1 的值) 
  • 1
  • 1
  • 1

2.4 人爲數組

人爲數組提供了一種去顯示存儲器塊(數組節或動態分配的存儲區)內容的方法。早期的調試程序沒有很好的方法將任意的指針換成一個數組。就像對待參數同樣,讓咱們查看內存中在變量h後面的10個整數,一個動態數組的語法以下所示:

base@length
  • 1
  • 1
  • 1

所以,要想顯示在h後面的10個元素,可使用h@10:

(gdb)print h@10 $13=(-1,345,23,-234,0,0,0,98,345,10) 
  • 1
  • 2
  • 1
  • 2
  • 1
  • 2

四:斷點(breakpoint)

1. break命令(能夠簡寫爲b)

能夠用來在調試的程序中設置斷點,該命令有以下四種形式:

1. break line-number 使程序剛好在執行給定行以前中止。 2. break function-name 使程序剛好在進入指定的函數以前中止。 3. break line-or-function if condition 若是condition(條件)是真,程序到達指定行或函數時中止。 4. break routine-name 在指定例程的入口處設置斷點 
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

若是該程序是由不少原文件構成的,你能夠在各個原文件中設置斷點,而不是在當前的原文件中設置斷點,其方法以下:

(gdb)   break   filename:line-number (gdb) break filename:function-name
  • 1
  • 2
  • 1
  • 2
  • 1
  • 2

要想設置一個條件斷點,能夠利用break if命令,以下所示:

(gdb)   break   line-or-function if expr
  • 1
  • 1
  • 1

例:

(gdb)   break 46 if testsize==100
  • 1
  • 1
  • 1

從斷點繼續運行:countinue(c) 命令

五.斷點的管理

1.顯示當前gdb的斷點信息:

(gdb)   info   break
  • 1
  • 1
  • 1

他會以以下的形式顯示全部的斷點信息:

Num   Type   Disp   Enb   Address   What     
  1 breakpoint keep y 0x000028bc in init_random at qsort2.c:155 2 breakpoint keep y 0x0000291c in init_organ at qsort2.c:168 (gdb)
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

2.刪除指定的某個斷點:

(gdb)   delete breakpoint 1
  • 1
  • 1
  • 1

該命令將會刪除編號爲1的斷點,若是不帶編號參數,將刪除全部的斷點

(gdb)   delete breakpoint
  • 1
  • 1
  • 1

3.禁止使用某個斷點

(gdb)   disable   breakpoint 1
  • 1
  • 1
  • 1

該命令將禁止斷點 1,同時斷點信息的 (Enb)域將變爲 n

4.容許使用某個斷點

(gdb)   enable   breakpoint 1
  • 1
  • 1
  • 1

該命令將容許斷點 1,同時斷點信息的 (Enb)域將變爲 y

5.清除原文件中某一代碼行上的全部斷點

(gdb)clean   number
  • 1
  • 1
  • 1

注:number 爲原文件的某個代碼行的行號 
Clear清除全部的已定義的中止點。 
clear <function>clear <filename:function>清除全部設置在函數上的中止點。 
clear <linenum>clear <filename:linenum>清除全部設置在指定行上的中止點。

六.變量的檢查和賦值

  1. whatis:識別數組或變量的類型
  2. ptype:比whatis的功能更強,他能夠提供一個結構的定義
  3. set variable:將值賦予變量
  4. print 除了顯示一個變量的值外,還能夠用來賦值

七.單步執行

  1. next(n) 不進入的單步執行
  2. step(s) 進入的單步執行
  3. finish 退出該函數返回到它的調用函數中

八.函數的調用

  1. call name 調用和執行一個函數
(gdb)   call   gen_and_sork(   1234,1,0 ) (gdb) call printf(「abcd」) $1=4 
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

九.機器語言工具

有一組專用的gdb變量能夠用來檢查和修改計算機的通用寄存器,gdb提供了目前每一臺計算機中實際使用的4個寄存器的標準名字: 
1. $pc: 程序計數器 
2. $fp: 幀指針(當前堆棧幀) 
3. $sp: 棧指針 
4. $ps: 處理器狀態

十.信號

gdb一般能夠捕捉到發送給它的大多數信號,經過捕捉信號,它就可決定對於正在運行的進程要作些什麼工做。例如,按CTRL-C將中斷信號發送給gdb,一般就會終止gdb。可是你或許不想中斷gdb,真正的目的是要中斷gdb正在運行的程序,所以,gdb要抓住該信號並中止它正在運行的程序,這樣就能夠執行某些調試操做。

Handle命令可控制信號的處理,他有兩個參數,一個是信號名,另外一個是接受到信號時該做什麼。幾種可能的參數是: 
1. nostop 接收到信號時,不要將它發送給程序,也不要中止程序。 
2. stop 接受到信號時中止程序的執行,從而容許程序調試;顯示一條表示已接受到信號的消息(禁止使用消息除外) 
3. print 接受到信號時顯示一條消息 
4. noprint 接受到信號時不要顯示消息(並且隱含着不中止程序運行) 
5. pass 將信號發送給程序,從而容許你的程序去處理它、中止運行或採起別的動做。 
6. nopass 中止程序運行,但不要將信號發送給程序。

例如,假定你截獲SIGPIPE信號,以防止正在調試的程序接受到該信號,並且只要該信號一到達,就要求該序中止,並通知你。要完成這一任務,可利用以下命令:

(gdb)   handle   SIGPIPE   stop   print
  • 1
  • 1
  • 1

請注意,UNIX的信號名老是採用大寫字母!你能夠用信號編號替代信號名 
若是你的程序要執行任何信號處理操做,就須要可以測試其信號處理程序,爲此,就須要一種能將信號發送給程序的簡便方法,這就是signal命令的任務。該 命令的參數是一個數字或者一個名字,如SIGINT。假定你的程序已將一個專用的SIGINT(鍵盤輸入,或CTRL-C;信號2)信號處理程序設置成採 取某個清理動做,要想測試該信號處理程序,你能夠設置一個斷點並使用以下命令:

(gdb)   signal 2 continuing with signal SIGINT(2)
  • 1
  • 2
  • 1
  • 2
  • 1
  • 2

該程序繼續執行,可是當即傳輸該信號,並且處理程序開始運行.

十一. 原文件的搜索

  1. search text:該命令可顯示在當前文件中包含text串的下一行。
  2. Reverse-search text:該命令能夠顯示包含text 的前一行。

十二.UNIX接口

shell 命令可啓動UNIX外殼,CTRL-D退出外殼,返回到 gdb.

十三.命令的歷史

爲了容許使用歷史命令,可以使用 set history expansion on 命令

(gdb)   set history expansion on
  • 1
  • 1
  • 1

小結:經常使用的gdb命令

backtrace   //顯示程序中的當前位置和表示如何到達當前位置的棧跟蹤(同義詞:where) breakpoint  //在程序中設置一個斷點 cd  //改變當前工做目錄 clear  //刪除剛纔中止處的斷點 commands  //命中斷點時,列出將要執行的命令 (#add至關於vs的when hit) continue  //從斷點開始繼續執行 delete  //刪除一個斷點或監測點;也可與其餘命令一塊兒使用 display  //程序中止時顯示變量和表達時 down  //下移棧幀,使得另外一個函數成爲當前函數 frame  //選擇下一條continue命令的幀 info  //顯示與該程序有關的各類信息 jump  //在源程序中的另外一點開始運行 kill  //異常終止在gdb 控制下運行的程序 list  //列出相應於正在執行的程序的原文件內容 next  //執行下一個源程序行,從而執行其總體中的一個函數 print  //顯示變量或表達式的值 pwd  //顯示當前工做目錄 ptype  //顯示一個數據結構(如一個結構或C++類)的內容 quit  //退出gdb reverse-search  //在源文件中反向搜索正規表達式 run  //執行該程序 search  //在源文件中搜索正規表達式 set variable  //給變量賦值 signal  //將一個信號發送到正在運行的進程 step  //執行下一個源程序行,必要時進入下一個函數 undisplay  //display命令的反命令,不要顯示錶達式 until  //結束當前循環 up  //上移棧幀,使另外一函數成爲當前函數 watch  //在程序中設置一個監測點(即數據斷點) whatis  //顯示變量或函數類型 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

gdb - GNU 調試器

提要 
gdb [-help] [-nx] [-q] [-batch] [-cd=dir] [-f] [-b bps] 
[-tty=dev] [-s symfile] [-e prog] [-se prog] [-c 
core] [-x cmds] [-d dir] [prog[core|procID]]

描述 
調試器(如GDB)的目的是容許你在程序運行時進入到某個程序內部去看看該程序在作什麼,或者在該程序崩潰時它在作什麼。

GDB主要能夠作4大類事(加上一些其餘的輔助工做),以幫助用戶在程序運行過程當中發現bug。

      o  啓動您的程序,並列出可能會影響它運行的一些信息
      o  使您的程序在特定條件下中止下來
      o  當程序停下來的時候,檢查發生了什麼
      o  對程序作出相應的調整,這樣您就能嘗試糾正一個錯誤並繼續發現其它錯誤

    您能使用GDB調試用C、C++、Modula-2寫的程序。等GNU Fortran編譯器準備好事後,GDB將提供對Fortran的支持

    GDB經過在命令行方式下輸入gdb來執行。啓動事後,GDB會從終端讀取命令,直到您輸入GDB命令quit使GDB退出。您能經過GDB命令help獲取在線幫助。

    您能以無參數無選項的形式運行GDB,不過一般的狀況是以一到兩個參數運行GDB,以待調試的可執行程序名爲參數
    gdb 程序名

    您能用兩個參數來運行GDB,可執行程序名與core文件(譯註:不知道怎麼翻譯好,就不翻譯了)。
    gdb 程序名 core

    您能夠以進程ID做爲第二個參數,以調式一個正在運行的進程
    gdb 程序名 1234
    將會把gdb附在進程1234之上(除非您正好有個文件叫1234,gdb老是先查找core文件)

   下面是一些最經常使用的GDB命令:

   file [filename]
          裝入想要調試的可執行文件

   kill [filename]
          終止正在調試的程序

   break [file:]function
          在(file文件的)function函數中設置一個斷點

   clear
          刪除一個斷點,這個命令須要指定代碼行或者函數名做爲參數

   run [arglist]
          運行您的程序 (若是指定了arglist,則將arglist做爲參數運行程序)

   bt Backtrace: 顯示程序堆棧信息

   print expr
          打印表達式的值

   continue
          繼續運行您的程序 (在中止以後,好比在一個斷點以後)

   list
          列出產生執行文件的源代碼的一部分

   next
          單步執行 (在中止以後); 跳過函數調用

   nexti
          執行下一行的源代碼中的一條彙編指令

   set
          設置變量的值。例如:set nval=54 將把54保存到nval變量中

   step
          單步執行 (在中止以後); 進入函數調用

   stepi
          繼續執行程序下一行源代碼中的彙編指令。若是是函數調用,這個命令將進入函數的內部,單步執行函數中的彙編代碼

   watch
          使你能監視一個變量的值而無論它什麼時候被改變

   rwatch
          指定一個變量,若是這個變量被讀,則暫停程序運行,在調試器中顯示信息,並等待下一個調試命令。參考rwatch和watch命令

   awatch
          指定一個變量,若是這個變量被讀或者被寫,則暫停程序運行,在調試器中顯示信息,並等待下一個調試命令。參考rwatch和watch命令

   Ctrl-C
          在當前位置中止執行正在執行的程序,斷點在當前行

   disable
          禁止斷點功能,這個命令須要禁止的斷點在斷點列表索引值做爲參數

   display
          在斷點的中止的地方,顯示指定的表達式的值。(顯示變量)

   undisplay
          刪除一個display設置的變量顯示。這個命令須要將display list中的索引作參數

   enable
          容許斷點功能,這個命令須要容許的斷點在斷點列表索引值做爲參數

   finish
          繼續執行,直到當前函數返回

   ignore
          忽略某個斷點制定的次數。例:ignore 4 23 忽略斷點4的23次運行,在第24次的時候中斷

   info [name]
          查看name信息

   load
          動態載入一個可執行文件到調試器

   xbreak
          在當前函數的退出的點上設置一個斷點

   whatis
          顯示變量的值和類型

   ptype
          顯示變量的類型

   return
          強制從當前函數返回

   txbreak
          在當前函數的退出的點上設置一個臨時的斷點(只可以使用一次)

   make
          使你能不退出 gdb 就能夠從新產生可執行文件

   shell
          使你能不離開 gdb 就執行 UNIX shell 命令

   help [name]
          顯示GDB命令的信息,或者顯示如何使用GDB的整體信息

   quit
          退出gdb.


   要獲得全部使用GDB的資料,請參考Using GDB: A Guide to the GNU
   Source-Level  Debugger,  by Richard M. Stallman and Roland
   H. Pesch.  當用info查看的時候,也能看到相同的文章
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132

選項 
任何參數而非選項指明瞭一個可執行文件及core 文件(或者進程ID);所 
遇到的第一個未關聯選項標誌的參數與 ‘-se’ 選項等價,第二個,若是存 
在,且是一個文件的名字,則等價與 ‘-c’ 選項。許多選項都有一個長格式 
與短格式;都會在這裏表示出來。若是你把一個長格式截短,只要不引發歧 
義,那麼它仍是能夠被識別。(若是你願意,你可使用 ‘+’ 而非 ‘-’ 標 
記選項參數,不過咱們在例子中仍然聽從一般的慣例)

-help

   -h     列出全部選項,並附簡要說明。  

   -symbols=file

   -s file
          讀出文件(file)中的符號表。

   -write 
          開通(enable)往可執行文件和核心文件寫的權限。

   -exec=file

   -e file
          在適當時候把File做爲可執行的文件執行,來檢測與core dump結合的數據。
   -se File
          從File讀取符號表並把它做爲可執行文件。
   -core File
   -c File
          把File做爲core dump來執行。
   -command=File
   -x File
          從File中執行GDB命令。
   -directory=Directory
   -d Directory
          把Dicrctory加入源文件搜索的路徑中。
   -nx
   -n
          不從任何.gdbinit初始化文件中執行命令。一般狀況下,這些文件中的命令是在全部命令選項和參數處理完後才執行。
   -quiet
   -q
          "Quiet".不輸入介紹和版權信息。這些信息輸出在batch模式下也被關閉。
   -batch
          運行batch模式。在處理完全部用'-x'選項指定的命令文件(還有'.gdbi-nit',若是沒禁用)後退出,並返回狀態碼0.若是在命令文件中的命令被
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

執行時發生錯誤,則退出,並返回狀態碼非0.batch模式對於運行GDB做爲過濾器也許頗有用,好比要從另外一臺電腦上下載並運行一個程序;爲了讓這些更有用,當 
在batch模式下運行時,消息:Program exited normally.(不論何時,一個程序在GDB控制下終止運行,這條消息都會正常發出.),將不會發出. 
-cd=Directory 
運行GDB,使用Directory做爲它的工做目錄,取代當前工做目錄. 
-fullname 
-f 
當Emacs讓GDB做爲一個子進程運行時,設置這個選項.它告訴GDB每當一個堆棧結構(棧幀)顯示出來(包括每次程序中止)就用標準的,認同的方式 
輸出文件全名和行號.這裏,認同的格式看起來像兩個’ 32’字符,緊跟文件名,行號和字符位置(由冒號,換行符分隔).Emacs同GDB的接口程序使用這兩個’ 32’字 
符做爲一個符號爲框架來顯示源代碼. 
-b Bps 
設置行速(波特率或bits/s).在遠程調試中GDB在任何串行接口中使用的行速. 
-tty=Device 
使用Device做爲你程序運行的標準輸入輸出.

gdb主要調試的是C/C++的程序。要調試C/C++的程序,首先在編譯時,必需要把調試信息加到可執行文件中。使用編譯器(cc/gcc/g++)的 -g 參數便可。如:

[david@DAVID david]$ gcc -g hello.c -o hello

[david@DAVID david]$ g++ -g hello.cpp -o hello

若是沒有-g,將看不見程序的函數名和變量名,代替它們的全是運行時的內存地址。當用-g把調試信息加入,併成功編譯目標代碼之後,看看如何用gdb來調試。

啓動gdb的方法有如下幾種:

  1. gdb 
    program也就是執行文件,通常在當前目錄下。

  2. gdb core 
    用gdb同時調試一個運行程序和core文件,core是程序非法執行後,core dump後產生的文件。

  3. gdb 
    若是程序是一個服務程序,那麼能夠指定這個服務程序運行時的進程ID。gdb會自動attach上去,並調試它。program應該在PATH環境變量中搜索獲得。

●在Linux下用ps(第一章已經對ps做了介紹)查看正在運行的程序的PID(進程ID),而後用gdb PID格式掛接正在運行的程序。

●先用gdb 關聯上源代碼,並進行gdb,在gdb中用attach命令來掛接進程的PID,並用detach來取消掛接的進程。

gdb啓動時,能夠加上一些gdb的啓動開關,詳細的開關能夠用gdb -help查看。下面只列舉一些比較經常使用的參數:

-symbols

-s

從指定文件中讀取符號表。

-se file

從指定文件中讀取符號表信息,並把它用在可執行文件中。

-core

-c

調試時core dump的core文件。

-directory

-d

加入一個源文件的搜索路徑。默認搜索路徑是環境變量中PATH所定義的路徑。

4.1.1 gdb的命令概貌 
gdb的命令不少,gdb將之分紅許多種類。help命令只是列出gdb的命令種類,若是要看其中的命令,可使用help 命令。如:

(gdb) help data

也能夠直接用help [command]來查看命令的幫助。

gdb中,輸入命令時,能夠不用輸入所有命令,只用輸入命令的前幾個字符就能夠了。固然,命令的前幾個字符應該標誌着一個唯一的命令,在linux下,能夠按兩次TAB鍵來補齊命令的全稱,若是有重複的,那麼gdb會把它所有列出來。

示例一:在進入函數func時,設置一個斷點。能夠輸入break func,或是直接輸入b func。

(gdb) b func

Breakpoint 1 at 0x804832e: file test.c, line 5.

(gdb)

示例二:輸入b按兩次TAB鍵,你會看到全部b開頭的命令。

(gdb) b

backtrace break bt

要退出gdb時,只用輸入quit或其簡稱q就好了。

4.1.2 gdb中運行Linux的shell程序 
在gdb環境中,能夠執行Linux的shell命令:

shell

調用Linux的shell來執行,環境變量SHELL中定義的Linux的shell將會用來執行。若是SHELL沒有定義,那就使用Linux的標準shell:/bin/sh(在Windows中使用Command.com或cmd.exe)。

還有一個gdb命令是make:

make

能夠在gdb中執行make命令來從新build本身的程序。這個命令等價於shell make 。

4.1.3 在gdb中運行程序 
當以gdb 方式啓動gdb後,gdb會在PATH路徑和當前目錄中搜索的源文件。如要確認gdb是否讀到源文件,可以使用l或list命令,看看gdb是否能列出源代碼。

在gdb中,運行程序使用r或是run命令。程序的運行,有可能須要設置下面四方面的事。

  1. 程序運行參數 
    set args 可指定運行時參數。如:

set args 10 20 30 40 50

show args 命令能夠查看設置好的運行參數。

  1. 運行環境 
    path 可設定程序的運行路徑。

show paths 查看程序的運行路徑。

set environment varname [=value] 設置環境變量。如:

set env USER=hchen

show environment [varname] 查看環境變量。

  1. 工做目錄 
    cd 至關於shell的cd命令。

pwd 顯示當前的所在目錄。

  1. 程序的輸入輸出 
    info terminal 顯示程序用到的終端的模式。

使用重定向控制程序輸出。如:

run > outfile

tty命令能夠指寫輸入輸出的終端設備。如:

tty /dev/ttyb

4.1.4 調試已運行的程序 
調試已經運行的程序有兩種方法:

● 在Linux下用ps(第一章已經對ps做了介紹)查看正在運行的程序的PID(進程ID),而後用gdb PID格式掛接正在運行的程序。

● 先用gdb 關聯上源代碼,並進行gdb,在gdb中用attach命令來掛接進程的PID,並用detach來取消掛接的進程。

4.1.5 暫停/恢復程序運行 
調試程序中,暫停程序運行是必需的,gdb能夠方便地暫停程序的運行。能夠設置程序在哪行停住,在什麼條件下停住,在收到什麼信號時停往等,以便於用戶查看運行時的變量,以及運行時的流程。

當進程被gdb停住時,可使用info program 來查看程序是否在運行、進程號、被暫停的緣由。

在gdb中,有如下幾種暫停方式:斷點(BreakPoint)、觀察點(WatchPoint)、捕捉點(CatchPoint)、信號(Signals)及線程中止(Thread Stops)。

若是要恢復程序運行,可使用c或是continue命令。

  1. 設置斷點(BreakPoint) 
    用break命令來設置斷點。有下面幾種設置斷點的方法:

break

在進入指定函數時停住。C++中可使用class::function或function(type,type)格式來指定函數名。

break

在指定行號停住。

break +offset

break -offset

在當前行號的前面或後面的offset行停住。offiset爲天然數。

break filename:linenum

在源文件filename的linenum行處停住。

break filename:function

在源文件filename的function函數的入口處停住。

break *address

在程序運行的內存地址處停住。

break

該命令沒有參數時,表示在下一條指令處停住。

break … if

condition表示條件,在條件成立時停住。好比在循環體中,能夠設置break if i=100,表示當i爲100時停住程序。

查看斷點時,可以使用info命令,以下所示(注:n表示斷點號):

info breakpoints [n]

info break [n]

  1. 設置觀察點(WatchPoint) 
    觀察點通常用來觀察某個表達式(變量也是一種表達式)的值是否變化了。若是有變化,立刻停住程序。有下面的幾種方法來設置觀察點:

watch

爲表達式(變量)expr設置一個觀察點。一旦表達式值有變化時,立刻停住程序。

rwatch

當表達式(變量)expr被讀時,停住程序。

awatch

當表達式(變量)的值被讀或被寫時,停住程序。

info watchpoints

列出當前設置的全部觀察點。

  1. 設置捕捉點(CatchPoint) 
    可設置捕捉點來補捉程序運行時的一些事件。如載入共享庫(動態連接庫)或是C++的異常。設置捕捉點的格式爲:

catch

當event發生時,停住程序。event能夠是下面的內容:

● throw 一個C++拋出的異常 (throw爲關鍵字)。

● catch 一個C++捕捉到的異常 (catch爲關鍵字)。

● exec 調用系統調用exec時(exec爲關鍵字,目前此功能只在HP-UX下有用)。

● fork 調用系統調用fork時(fork爲關鍵字,目前此功能只在HP-UX下有用)。

● vfork 調用系統調用vfork時(vfork爲關鍵字,目前此功能只在HP-UX下有)。

● load 或 load 載入共享庫(動態連接庫)時 (load爲關鍵字,目前此功能只在HP-UX下有用)。

● unload 或 unload 卸載共享庫(動態連接庫)時 (unload爲關鍵字,目前此功能只在HP-UX下有用)。

tcatch

只設置一次捕捉點,當程序停住之後,應點被自動刪除。

  1. 維護中止點 
    上面說了如何設置程序的中止點,gdb中的中止點也就是上述的三類。在gdb中,若是以爲已定義好的中止點沒有用了,可使用delete、clear、disable、enable這幾個命令來進行維護。

Clear

清除全部的已定義的中止點。

clear

clear

清除全部設置在函數上的中止點。

clear

clear

清除全部設置在指定行上的中止點。

delete [breakpoints] [range…]

刪除指定的斷點,breakpoints爲斷點號。若是不指定斷點號,則表示刪除全部的斷點。range 表示斷點號的範圍(如:3-7)。其簡寫命令爲d。

比刪除更好的一種方法是disable中止點。disable了的中止點,gdb不會刪除,當還須要時,enable便可,就好像回收站同樣。

disable [breakpoints] [range…]

disable所指定的中止點,breakpoints爲中止點號。若是什麼都不指定,表示disable全部的中止點。簡寫命令是dis.

enable [breakpoints] [range…]

enable所指定的中止點,breakpoints爲中止點號。

enable [breakpoints] once range…

enable所指定的中止點一次,當程序中止後,該中止點立刻被gdb自動disable。

enable [breakpoints] delete range…

enable所指定的中止點一次,當程序中止後,該中止點立刻被gdb自動刪除。

  1. 中止條件維護 
    前面在介紹設置斷點時,提到過能夠設置一個條件,當條件成立時,程序自動中止。這是一個很是強大的功能,這裏,專門介紹這個條件的相關維護命令。

通常來講,爲斷點設置一個條件,可以使用if關鍵詞,後面跟其斷點條件。而且,條件設置好後,能夠用condition命令來修改斷點的條件(只有break和watch命令支持if,catch目前暫不支持if)。

condition

修改斷點號爲bnum的中止條件爲expression。

condition

清除斷點號爲bnum的中止條件。

還有一個比較特殊的維護命令ignore,能夠指定程序運行時,忽略中止條件幾回。

ignore

表示忽略斷點號爲bnum的中止條件count次。

  1. 爲中止點設定運行命令 
    可使用gdb提供的command命令來設置中止點的運行命令。也就是說,當運行的程序在被停住時,咱們可讓其自動運行一些別的命令,這頗有利行自動化調試。

commands [bnum]

… command-list …

end

爲斷點號bnum指定一個命令列表。當程序被該斷點停住時,gdb會依次運行命令列表中的命令。

例如:

break foo if x>0

commands

printf 「x is %d\n」,x

continue

end

斷點設置在函數foo中,斷點條件是x>0,若是程序被斷住後,也就是一旦x的值在foo函數中大於0,gdb會自動打印出x的值,並繼續運行程序。

若是要清除斷點上的命令序列,那麼只要簡單地執行一下commands命令,並直接在輸入end就好了。

  1. 斷點菜單  在C++中,可能會重複出現同一個名字的函數若干次(函數重載)。在這種狀況下,break 不能告訴gdb要停在哪一個函數的入口。固然,可使用break
相關文章
相關標籤/搜索