您好,登錄后才能下訂單哦!
小編給大家分享一下Linux系統(tǒng)中GDB是什么,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
GDB調試是C/C++程序員必須掌握的技能。
GDB 可以做四種主要的事情(以及支持這些事情的其他事情)來幫助你捕獲行為中的錯誤:
啟動你的程序,并指定可能影響其行為的所有內容。
使程序在指定條件下停止。
檢查程序停止時發(fā)生的情況。
更改程序中的內容,以便你可以嘗試糾正一個錯誤的影響,然后繼續(xù)學習另一個錯誤。
這些程序可能與GDB(本機)在同一臺計算機上執(zhí)行,在另一臺計算機(遠程)上或在模擬器上執(zhí)行。GDB可以在大多數(shù)流行的UNIX和Microsoft Windows變體以及Mac OS X上運行。
  通過 gcc 的 -g 選項,將調試信息加到可執(zhí)行文件中。
$ gcc -g hello.c -o hello1
  如果使用 Makefile 構建,一般要在 CFLAGS 中指定 -g 選項。
CFLAGS := -Wall -O2 -g1
  注意,給 GCC 編譯器加上優(yōu)化選項后,實際的執(zhí)行順序可能由于優(yōu)化而與源代碼順序不同,因此利用調試器跟蹤運行時,有時會執(zhí)行到莫名奇妙的地方,從而造成混亂。
  使用命令 gdb 程序名啟動。
  可以在函數(shù)名和行號等上設置斷點。程序到達斷點就會自動暫停運行。此時可以查看該時刻的變量值,顯示棧幀、重新設置斷點或重新運行等。斷點命令 break 可以簡寫為 b,命令為 break 。      斷點可以通過函數(shù)名、當前文件內的行號來設置,也可以先指定文件名再指定行號,還可以指定與暫停位置的偏移量,或者用地址來設置。格式:
格式 | 說明 |
---|---|
break | 對當前正在執(zhí)行的文件中的指定函數(shù)設置斷點 |
break | 對當前正在執(zhí)行的文件中的特定行設置斷點 |
break 文件名:行號 | 對指定文件的指定行設置斷點,最常用的設置斷點方式 |
break 文件名:函數(shù)名 | 對指定文件的指定函數(shù)設置斷點 |
break | 當前指令行+/-偏移量出設置斷點 |
break | 指定地址處設置斷點 |
     設置好的斷點可以通過 info break 確認。
  使用 run 參數(shù) 命令開始運行,其中參數(shù)為可執(zhí)行程序的參數(shù)。如果設置了斷點,會執(zhí)行到設置了斷點的位置后暫停運行。可以簡寫為 r。
  backtrace 命令可以在遇到斷點或異常而暫停執(zhí)行時顯示棧幀,該命令簡寫為 bt。此外,backtrace 的別名還有 where 和 info stack。
格式 | 說明 |
---|---|
bt | 顯示所有棧幀 |
bt | 只顯示開頭 N 個棧幀 |
bt | 只顯示最后 N 個棧幀 |
bt full | 不僅顯示 backtrace,還要顯示局部變量 |
bt full |
     顯示棧幀之后,就可以看出程序在何處停止,以及程序的調用路徑。
  print 命令可以顯示變量,可以簡寫為 p。      格式:print 變量。
  info registers 可以顯示寄存器,簡寫為 info reg。      在寄存器名之前添加 $,顯示寄存器的內容,例如 p $eax。   p/格式 $寄存器 可以指定寄存器的顯示格式,例如 p/c $eax??墒褂玫母袷饺缦拢?/p>
格式 | 說明 |
---|---|
x | 顯示為十六進制數(shù) |
d | 顯示為十進制數(shù) |
u | 顯示為無符號十進制數(shù) |
o | 顯示為八進制數(shù) |
t | 顯示為二進制數(shù) |
a | 地址 |
c | 顯示為字符(ASCII) |
f | 浮點小數(shù) |
s | 顯示為字符串 |
i | 顯示為機器語言,僅在顯示內存的 x 命令中可用 |
顯示詳細信息
     程序指針可以寫為 ,也可以寫為eip,使用 p $pc 顯示程序指針內容。程序指針指向當前程序的運行點的地址。      x 命令可以顯示內存的內容,格式:x/ 。例如 x/i $ps,顯示匯編指令。      一般使用 x 命令時,格式為 x/
單位 | 說明 |
---|---|
b | 字節(jié) |
h | 半字(2 字節(jié)) |
w | 字(4 字節(jié))(默認值) |
g | 雙字(8 字節(jié)) |
  例如命令 x\10i $pc 顯示從 pc 所指地址開始的 10 條指令。      反匯編命令 disassemble,簡寫為 disas。格式:
disassemble。反匯編當前整個函數(shù)。
disassemble 程序計數(shù)器。反匯編程序計數(shù)器所在函數(shù)的整個函數(shù)。
disassemble 開始地址 結束地址。反匯編從開始地址到結束地址之間的部分。
  單步執(zhí)行的意思時根據(jù)源代碼一行一行地執(zhí)行。執(zhí)行源代碼中一行的命令為 next ,簡寫為 n。執(zhí)行時如果遇到函數(shù)調用,想執(zhí)行到函數(shù)內部,使用 step 命令,簡寫為 p。   如果要逐條執(zhí)行匯編指令,可以分別使用 nexti 和 stepi 命令。
  使用 continue 命令繼續(xù)運行程序,簡寫為 c。程序會在遇到斷點后再次暫停運行。使用 continue 命令指定忽略斷點的次數(shù)。
  大型軟件或大量使用指針的程序中,很難弄清變量在什么地方被改變,要想找到變量在何處被改變,可以使用 watch 命令(監(jiān)視點,watchpoint)。格式如下:
watch 。表達式發(fā)生變化時暫停運行。
awatch 。表達式被訪問、改變時暫停運行。
rwatch 。表達式被訪問時暫停運行。
  需要注意,設置監(jiān)視點可能會降低運行速度。
  delete 命令刪除斷點和監(jiān)視點,簡寫為 d。格式為 delete ,表示刪除編號指示的斷點或監(jiān)視點,編號可以用命令 info b 查看。   clear 命令刪除已定義的斷點??捎妹畎ǎ?    clear     clear     clear 文件名:行號     clear 文件名:函數(shù)名      disable 命令禁用斷點。命令格式如下:     disable:禁用所有斷點。     disable :禁用指定斷點。     disable display :禁用 display 命令定義的自動顯示。     disable mem :禁用 mem 命令定義的內存區(qū)域。      enable 命令用于啟用斷點。命令格式如下:     enable     enable     enable once :使指定的斷點只啟用一次。     enable delete     enable display     enable mem
  硬件斷點(hbreak),適用于 ROM 空間等無法修改的內存區(qū)域中的程序,在有些架構中無法使用。      臨時斷點(tbreak)和臨時硬件斷點(thbreak),在運行到該處時暫停,此時斷點會被刪除,在只需要停止一次時用起來方便。
  格式:set variable 。例如命令 set variable options = 0,將變量 options 的值改成了 0。
  使用 generate-core-file 可將調試中的進程生成內核轉儲文件。通過內核轉儲文件和調試對象,查看生成轉儲文件時的運行歷史。      gcore 命令可以從命令行直接生成內核轉儲文件。在命令行使用 gcore pid,其中 pid 為進程號。該命令無須停止正在運行的程序以獲得內核轉儲文件,當需要在其他機器上單獨分析問題原因,或是分析客戶現(xiàn)場發(fā)生的問題時十分有用。
  內核轉儲(core dump)的最大好處是,它能保存問題發(fā)生時的狀態(tài)。只要有問題發(fā)生時程序的可執(zhí)行文件和內核轉儲,就可以知道進程當前的狀態(tài)。
  大多數(shù) Linux 發(fā)行版默認關閉了內核轉儲功能,使用 ulimit 命令可以查看當前的內核轉儲功能是否有效。
$ ulimit -c 012
  -c 選項表示內核轉儲文件的大小限制,0 表示內核轉儲無效。開啟內核轉儲執(zhí)行命令:
$ ulimit -c unlimited or $ ulimit -c 上限123
  unlimited 意思是不限制內核轉儲文件的大小,發(fā)生問題時進程的內存就可以全部轉儲到內核轉儲文件中?;蛘咴O置內核轉儲文件的上限,在參數(shù)中指定上限大小,單位為 Kb。      程序發(fā)生異常時會在當前目錄下生成內核轉儲文件。例如程序 a.out 生成轉儲文件 core,使用以下方式啟動 GDB:
$ gdb -c core ./a.out1
     使用 GDB 的 list 命令可以查看附近的源代碼。命令使用方法
格式 | 說明 |
---|---|
list | 顯示程序第 linenum 行周圍的源代碼 |
list | 顯示函數(shù)名為 function 的函數(shù)的源代碼 |
list | 顯示當前行后面的源代碼 |
list – | 顯示當前行前面的源代碼 |
set listsize | 設置一次顯示源代碼的行數(shù) |
show listsize | 查看當前 listsize 的設置 |
list | 顯示從 first 行到 last 行之間的源代碼 |
list , | 顯示從當前行到 last 行之間的源代碼 |
list + | 往后顯示源代碼 |
  轉儲保存位置的完整路徑可以通過 sysctl 變量 kernel.core_pattern 設置。在文件 /etc/sysctl.conf 中設置如下:
$ cat /etc/sysctl.conf kernel.core_pattern = /var/core/%t-%e-%p-%c.core kernel.core_uses_pid = 0 $ sysctl -p1234
     此外,還可以在 /proc/sys/kernel 下修改設置。   /proc/sys/kernel/core_uses_pid 可以控制產(chǎn)生的 core 文件的文件名中是否添加 pid 作為擴展 ,如果添加則文件內容為 1 ,否則為 0。   proc/sys/kernel/core_pattern 可以設置格式化的 core 文件保存位置或文件名 ,可以這樣修改 :
$ echo "/corefile/core-%e-%p-%t" > core_pattern1
     kernel.core_pattern 中可以設置的格式符如下:
格式符 | 說明 |
---|---|
%% | % 字符本身 |
%p | 被轉儲進程的進程 ID(PID) |
%u | 被轉儲進程的真實用戶 ID(real UID) |
%g | 被轉儲進程的真實組 ID(real GID) |
%s | 引發(fā)轉儲的信號編號 |
%t | 轉儲時刻(從 1970/1/1 0:00 開始的秒數(shù)) |
%h | 主機名(同 uname(2) 返回的 nodename) |
%e | 可執(zhí)行文件名 |
%c | 轉儲文件的大小上限(內核版本 2.6.24 后可用) |
  修改 /etc/sysctl.conf中 的 kernel.core_pattern 變量來設置。
$ cat /etc/sysctl.conf kernel.core_pattern= | usr/local/sbin/core_helper %t %e %p %c kernel.core_uses_pid= 0 $ sysctl -p1234
  core_helper 的內容:
$cat usr/local/sbin/core_helper #!/bin/sh execgzip ->/var/core/$1-$2-$3-$4.core.gz1234
  這樣,發(fā)生內核轉儲時就會在 /var/core 下生成壓縮的內核轉儲文件。
  /etc/profile 文件中可以設置開啟所有用戶的內核轉儲功能,默認情況下禁止內核轉儲:
ulimit -S -c 0 > /dev/null 2>&11
  將其修改為
ulimit -S -c unlimited > /dev/null 2>&11
     接下來要讓通過 init 腳本啟動的守護進程的內核轉儲功能有效。在 /etc/sysconfig/init 文件中添加一行命令。
DAEMON_COREFILE_LIMIT='unlimited'1
     最后在 /etc/sysctl.conf 中加入以下設置。
fs.suid_dumpable=11
  這個設置使得被 SUID 的程序也能內核轉儲。重新啟動啟動,就可以啟用整個系統(tǒng)的內核轉儲。      在我使用的Ubuntu、Debian和移植的嵌入式Linux系統(tǒng)中,沒有找到 /etc/sysconfig 文件夾。修改了文件 /etc/security/limits.conf,按照文件的內容提示修改,使 unlimited 永久生效。
  多進程程序如果使用龐大的共享內存,內核轉儲時所有進程的共享內存全部轉儲,會對磁盤造成巨大的壓力,轉儲過程也會加重系統(tǒng)的負載。由于共享內存的內容是相同的,只需要在某個進程中轉儲共享內存。      通過 /proc/
比特掩碼 | 內存類型 |
---|---|
比特 0 | 匿名專用內存 |
比特 1 | 匿名共享內存 |
比特 2 | file-backed 專用內從 |
比特 3 | file-backed 共享內存 |
比特 4 | ELF 文件映射(內核版本 2.6.24 后可用) |
  要跳過所有的共享內存區(qū)段,應將值改位 1。
  要調試已經(jīng)啟動的進程,或是調試陷入死循環(huán)而無法返回控制臺的進程時,可以使用 attach 命令。格式:attach
  break if ,這條命令將測試給定的條件,如果為幀則暫停運行。      如果斷點已經(jīng)存在,condition 命令給斷點添加觸發(fā)條件,condition 命令刪除指定編號斷點的觸發(fā)條件。
  ignore :在編號指定的斷點、監(jiān)視點或捕獲點忽略指定的次數(shù)。   continue : 達到指定次數(shù)前,執(zhí)行到斷電時不暫停。   s/stepi/n/nexti :執(zhí)行指定次數(shù)的相應命令。   finish:執(zhí)行完當前函數(shù)后暫停。   until:執(zhí)行完當前函數(shù)等代碼塊后暫停,如果是循環(huán),則在執(zhí)行完循環(huán)后暫停,常用于跳出循環(huán)。   until :執(zhí)行到指定地址停止。
  commands 命令可以定義在斷點終端后自動執(zhí)行的命令。格式如下:
(gdb) commands ... end1234
  通過 print 命令顯示過的值會記錄在內部的值歷史中。這些值通過 $ 進行引用,使用 show value 命令可以顯示歷史中的最后 10 個值。
變量 | 說明 |
---|---|
$ | 值歷史的最后一個值 |
$n | 值歷史的第 n 個值 |
$$ | 值歷史的倒數(shù)第 2 個值 |
$$n | 值歷史的倒數(shù)第 n 個值 |
$_ | x 命令顯示過的最后的地址 |
$__ | x 命令顯示過的最后的地址的值 |
$_eexitcode | 調試過程中的程序的返回代碼 |
$bpnum | 最后設置的斷點編號 |
     還可以隨意定義變量,變量以 $ 開頭,由英文字母和數(shù)字組成。例如:
(gdb) set $i=0 (gdb) p $i $i = 0123
  show history 將命令歷史保存到文件中,默認命令歷史文件位于 ./.gdb_history。
  set history expansion   show history expansion
  可以使用 csh 風格的 ! 字符。
  set history filename   show history filename
  將命令歷史保存到文件中。可以通過環(huán)境變量 GDBHISTFILE 改變默認文件名。
  set history save   show history save
  啟用命令歷史保存到文件和恢復的功能。
  set history size   show history size
  可設置保存到命令歷史中的命令數(shù)量。默認值為 256。
  Linux 環(huán)境下的初始化文件為 .gdbinit。如果存在 .gdbinit 文件,GDB 會在啟動之前將其作為命令文件運行。初始化文件和命令文件的運行順序如下。
1、$HOME/.gdbinit。
2、運行命令行選項。
3、./.gdbinit。
4、通過 -x 選項給出的命令文件。
  初始化文件和命令文件的語法相同。利用 define 命令可以自定義命令,document 命令給自定義命令添加說明,GDB 運行時使用 help 可以查看定義的命令。示例如下:
define li x/10i $pc end document li list machine instruction end123456
     除了初始化文件,還可以把設置寫在文件中,在運行 GDB 時讀取這些文件。命令為 source ,例如:
(gdb) source gdbcalc (gdb) p $log10(10000.0) $1 = 4123
  其中 gdbcalc 文件內容如下:
#!/usr/bin/gdb -x file /usr/bin/gdb start set $e = 2.7182818284590452354 set $pi = 3.14159265358979323846 set $fabs = (double (*)(double)) fabs set $sqrt = (double (*)(double)) sqrt set $cbrt = (double (*)(double)) cbrt set $exp = (double (*)(double)) exp set $exp2 = (double (*)(double)) exp2 set $exp10 = (double (*)(double)) exp10 set $log = (double (*)(double)) log set $log2 = (double (*)(double)) log2 set $log10 = (double (*)(double)) log10 set $pow = (double (*)(double, double)) pow set $sin = (double (*)(double)) sin set $cos = (double (*)(double)) cos set $tan = (double (*)(double)) tan set $asin = (double (*)(double)) asin set $acos = (double (*)(double)) acos set $atan = (double (*)(double)) atan set $atan2 = (double (*)(double, double)) atan set $sinh = (double (*)(double)) sinh set $cosh = (double (*)(double)) cosh set $tanh = (double (*)(double)) tanh set $asinh = (double (*)(double)) asinh set $acosh = (double (*)(double)) acosh set $atanh = (double (*)(double)) atanh22345678910111213141516171819202122232425262728
  GDB 常用命令及縮略形式如下表:
命令 | 簡寫形式 | 說明 |
---|---|---|
backtrace | bt、where | 顯示 backtrace |
break | 設置斷點 | |
continue | c、cont | 繼續(xù)運行 |
delete | d | 刪除斷點 |
finish | 運行到函數(shù)結束 | |
info breakpoints | 顯示斷點信息 | |
next | n | 執(zhí)行下一行 |
p | 顯示表達式 | |
run | r | 運行程序 |
step | s | 一次執(zhí)行一行,包括函數(shù)內部 |
x | 顯示內存內容 | |
until | u | 執(zhí)行到指定行 |
directory | dir | 插入目錄 |
disable | dis | 禁用斷點 |
down | do | 在當前調用的棧幀中選擇要顯示的棧幀 |
edit | e | 編輯文件或函數(shù) |
frame | f | 選擇要顯示的棧幀 |
forward-search | fo | 向前搜索 |
generate-core-file | gcore | 生成內核轉儲 |
help | h | 顯示幫助一覽 |
info | i | 顯示信息 |
list | l | 顯示函數(shù)或行 |
nexti | ni | 執(zhí)行下一行(以匯編代碼為單位) |
print-object | po | 顯示目標信息 |
sharedlibrary | share | 加載共享庫的符號 |
setpi | si | 執(zhí)行下一行 |
顯示詳細信息
以上是“Linux系統(tǒng)中GDB是什么”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業(yè)資訊頻道!
免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內容。