gdb除錯學習與實踐記錄 -- 常用命令解析1
目錄
info break 命令(簡寫為 info b)檢視加了哪些斷點及enable、disable 和 delete
Redis 原始碼解壓及編譯
- 進入生成的目錄使用 makefile 命令進行編譯
- 注意:
- 設定編譯器的選項時使用的是 CFLAGS 選項;如果專案使用的語言是 C++,那麼使用的編譯器一般是 g++,相對應的編譯器選項是 CXXFLAGS。
- 此處makefile 使用了 -j 選項,其值是 4,表示開啟 4 個程式同時編譯,加快編譯速度。
- src 目錄下生成多個可執行程式,其中 redis-server 和 redis-cli 是需要除錯的程式。
使用 GDB 附加 redis-server 這個程式
run 命令(簡寫為 r)啟動這個程式
- 這是 redis-server 啟動介面,假設程式已經啟動,再次輸入 run 命令則是重啟程式。
- 在 GDB 介面按 Ctrl + C 快捷鍵讓 GDB 中斷下來,再次輸入 r 命令,GDB 會詢問我們是否重啟程式,輸入 yes 確認重啟。
ontinue 命令 讓程式繼續執行
- 當 GDB 觸發斷點或者使用 Ctrl + C 命令中斷下來後,想讓程式繼續執行,只要輸入 continue 命令即可(簡寫為 c)。
- 如果 continue 命令繼續觸發斷點,GDB 就會再次中斷下來。
break 命令(簡寫為 b)新增斷點
break functionname 在函式名為 functionname 的入口處新增一個斷點 break LineNo 在當前檔案行號為 LineNo 處新增一個斷點 break filename:LineNo 在 filename 檔案行號為 LineNo 處新增一個斷點
- 對於一般的 Linux 程式來說,main() 函式是程式入口函式,redis-server 也不例外,知道了函式的名字,就可以直接在 main() 函式處新增一個斷點:
- 新增好了以後,使用 run 命令重啟程式,就可以觸發這個斷點了,GDB 會停在斷點處
- redis-server 預設埠號是 6379 ,這個埠號肯定是通過作業系統的 bind() 函式建立的,通過檔案搜尋,找到呼叫這個函式的檔案,其位於 anet.c 455 行。
- 使用 break 命令在這個地方加一個斷點:
- 由於程式繫結埠號是 redis-server 啟動時初始化的,為了能觸發這個斷點,再次使用 run 命令重啟下這個程式,GDB 第一次會觸發 main() 函式處的斷點,輸入 continue 命令繼續執行,接著觸發 anet.c:455處的斷點
- 現在斷點停在第 455 行,所以當前檔案就是 anet.c,可以直接使用“break 行號”新增斷點。
- 例如,可以在第 458 行、464 行、466 行分別加一個斷點,看看這個函式執行完畢後走哪個 return 語句退出,則可以執行:
- 新增好這三個斷點以後,使用 continue 命令繼續執行程式,發現程式執行到第 466 行中斷下來
- 說明 redis-server 繫結埠號並設定偵聽(listen)成功,再開啟一個 SSH 視窗,驗證一下,發現 6379 埠確實已經處於偵聽狀態了:
backtrace 命令(簡寫為 bt)檢視當前呼叫堆疊
- 接上,redis-server 現在中斷在 anet.c:466 行,可以通過 backtrace 命令來檢視當前的呼叫堆疊:
- 一共有 6 層堆疊,最頂層是 main() 函式,最底層是斷點所在的 anetListen() 函式,堆疊編號分別是 #0 ~ #5
- 如果想切換到其他堆疊處,可以使用 frame 命令(簡寫為 f),該命令的使用方法是“frame 堆疊編號(編號不加 #)”。在這裡依次切換至堆疊頂部,然後再切換回 #0 練習一下:
- 通過檢視上面的各個堆疊,可以得出這裡的呼叫層級關係,即:
- main() 函式在第 5162 行呼叫了 initServer() 函式
- initServer() 在第 2795 行呼叫了 listenToPort() 函式
- listenToPort() 在第 2651 行呼叫了 anetTcp6Server() 函式
- anetTcp6Server() 在第 524 行呼叫了 _anetTcpServer() 函式
- _anetTcpServer() 函式在第 501 行呼叫了 anetListen() 函式
- 當前斷點正好位於 anetListen() 函式中
info break 命令(簡寫為 info b)檢視加了哪些斷點及enable、disable 和 delete
- 通過上面的內容片段可以知道,目前一共增加了 6 個斷點,其他資訊比如每個斷點的位置(所在的檔案和行號)、記憶體地址、斷點啟用和禁用狀態資訊也一目瞭然。
- 如果我們想禁用某個斷點,使用“disable 斷點編號”就可以禁用這個斷點了,被禁用的斷點不會再被觸發;
- 被禁用的斷點也可以使用“enable 斷點編號”重新啟用。
- 使用 disable 1 以後,第一個斷點的 Enb 一欄的值由 y 變成 n,重啟程式也不會再次觸發:
- 如果 disable 命令和 enable 命令不加斷點編號,則分別表示禁用和啟用所有斷點:
- 使用“delete 編號”可以刪除某個斷點,如 delete 2 3 則表示要刪除的斷點 2 和斷點 3:
- 如果輸入 delete 不加命令號,則表示刪除所有斷點。
list 命令(簡寫為 l)檢視當前斷點處的程式碼
- 使用 frame 命令切換到剛才的堆疊 #3 處,然後輸入 list 命令看下效果:
- 斷點停在第 2795 行,輸入 list 命令以後,會顯示第 2795 行前後的 10 行程式碼,再次輸入 list 命令試一下:
- 程式碼繼續往後顯示 10 行,第一次輸入 list 命令會顯示斷點處前後的程式碼,繼續輸入 list 指令會以遞增行號的形式繼續顯示剩下的程式碼行,一直到檔案結束為止。
- list 指令還可以往前和往後顯示程式碼,命令分別是“list + (加號)”和“list - (減號)”:
- list 預設顯示多少行可以通過修改相關的 GDB 配置。
- list 不僅可以顯示當前斷點處的程式碼,也可以顯示其他檔案某一行的程式碼,更多的用法可以在 GDB 中輸入 help list 檢視(也可以通過):
- 可以使用 list FILE:LINENUM 來顯示某個檔案的某一行處的程式碼。
print 命令(簡寫為 p)在除錯過程中檢視變數的值、修改當前記憶體中的變數值
- 使用 print 命令分別列印出 server.port 、server.ipfd 、server.ipfd_count 的值
- 其中 server.ipfd 顯示 “{0 \}”,這是 GDB 顯示字串或字元資料特有的方式
- 當一個字串變數或者字元陣列或者連續的記憶體值重複若干次,GDB 就會以這種模式來顯示以節約空間。
- print 命令不僅可以顯示變數值,也可以顯示進行一定運算的表示式計算結果值,甚至可以顯示一些函式的執行結果值
- 如輸入 p &server.port 來輸出 server.port 的地址值
- 如果在 C++ 物件中,可以通過 p this 來顯示當前物件的地址,也可以通過 p *this 來列出當前物件的各個成員變數值
- 如果有三個變數可以相加( 假設變數名分別叫 a、b、c ),可以使用 p a + b + c 來列印這三個變數的結果值。
- 若 func() 是一個可以執行的函式,p func() 命令可以輸出該變數的執行結果
- 如,某個時刻,某個系統函式執行失敗了,通過系統變數 errno 得到一個錯誤碼,則可以使用 p strerror(errno) 將這個錯誤碼對應的文字資訊列印出來
- print 命令不僅可以輸出表示式結果,同時也可以修改變數的值
- 將上文中的埠號從 6379 改成 6400 試試:
- 一個變數值修改後能否起作用要看這個變數的具體位置和作用
- 對於表示式 int a = b / c ; 如果將 c 修改成 0 ,那麼程式就會產生除零異常。
- 利用 print 命令,不僅可以檢視程式執行過程中的各個變數的狀態值,也可以通過臨時修改變數的值來控制程式的行為。
ptype (print type)就是輸出一個變數的型別
- 輸出 Redis 堆疊 #4 的變數 server 和變數 server.port 的型別:
- 對於一個複合資料型別的變數,ptype 不僅列出了這個變數的型別( 這裡是一個名叫 redisServer 的結構體),而且詳細地列出了每個成員變數的欄位名。
相關文章
- GDB除錯使用記錄除錯
- GitHub學習除錯記錄Github除錯
- GDB除錯-從入門到實踐除錯
- Python 學習除錯記錄Python除錯
- GDB偵錯程式(學習筆記)筆記
- gdb除錯除錯
- GDB程式碼除錯與使用除錯
- 【PWA學習與實踐】(6) 在Chrome中除錯你的PWAChrome除錯
- GDB學習筆記筆記
- GDB除錯MySQL除錯MySql
- gdb除錯命令除錯
- GDB除錯指令除錯
- gdb除錯命令小結_與多檔案除錯_遠端除錯除錯
- NASM 與 GDB 簡易除錯指南ASM除錯
- spark學習筆記--Spark調優與除錯Spark筆記除錯
- stm32學習之除錯篇踩坑記錄除錯
- GDB 除錯程式碼除錯
- gdb除錯多程式除錯
- GDB除錯彙總除錯
- 用GDB除錯程式除錯
- GDB多程式除錯除錯
- gdb除錯多程序除錯
- gdb除錯快速上手除錯
- gdb除錯總結除錯
- flutter學習記錄-1Flutter
- Linux—gdb除錯簡單實現Linux除錯
- rabbitmq 實踐與學習心得分享(1)MQ
- 介紹 GDB 除錯 Go除錯Go
- GDB除錯命令詳解除錯
- C語言——gdb除錯C語言除錯
- 用GDB除錯程式(六)除錯
- Codeblocks和gdb除錯BloC除錯
- linux 下GDB除錯Linux除錯
- gdb高階除錯方法高階除錯
- 使用 gdb 工具除錯 Go除錯Go
- gdb高階除錯命令高階除錯
- gdb除錯coredump檔案除錯
- 線上除錯方案的思考與實踐除錯