GDB簡明教程:快速入門

2021-02-13 宅學部落


常在河邊走,哪有不溼鞋。經常編寫程序的人,又怎麼可能不遇到bug呢?沒有遇到過bug的程式設計師不是真正的程式設計師。當程序出現了bug,我們就需要debug,常見的程序錯誤按錯誤類型來分,一般可分為兩種:

編譯錯誤是指程序在編譯階段遇到的錯誤,比如語法錯誤、語義錯誤等。這種類型的錯誤編譯器一般會幫助我們檢查,當遇到此類錯誤時,編譯器就會停止編譯,給出錯誤或警告的信息,我們根據錯誤的提示,就可以很快解決掉。

運行錯誤是指程序在運行階段遇到的錯誤,比如段錯誤。在運行階段,為了能夠定位出現的錯誤,我們經常使用的方法是列印:將程序運行過程中的一些觀察變量列印出來,看是否符合正常的程序邏輯。列印方法簡單方便,但對於一些隱藏比較深的bug,或者一些跟內存相關的bug,此時再用「列印大法」可能就愛莫能助了。此時,我們經常使用的另一種方法是:單步調試。所謂單步調試,就是我們可以獲取到控制程序運行的權限,在人工操作下,程序可以「放慢腳步」,一步一步地執行,甚至可以暫停執行,方便我們觀察各個變量、內存、寄存器的值,看是否符合我們的預期。

在Windows下調試程序,我們一般是使用集成開發環境(IDE,Integrated Development Environment )內部集成的調試器(debugger),通過菜單欄的「調試(debug)」選項,就可以讓程序進入調試模式:可以單步執行程序、暫停程序運行、觀察變量或內存的值。

在Linux下調試程序,因為早期沒有成熟、好用的IDE,一般都是使用GDB來調試程序。GDB是「GNU Symblic Debugger」的縮寫,是GNU自由軟體下的一個產品,隨著版本不斷地更新迭代,目前最新的GDB版本不僅可以調試C語言程序,還可以調試C++、Go、Object-C等編譯型語言。

在Linux下開發程序,學會使用GDB是一項基本技能。在Windows下開發程序,在很多IDE內部,往往也集成了GDB,用戶可以通過圖形界面來調用GDB調試程序,也可以直接在DOS環境下直接通過GDB命令來調試程序。

本教程將會帶領大家熟悉和掌握程序調試常用的GDB命令,讓我們的開發工作更加高效。


很多Linux作業系統默認都已經安裝了GDB,所以在安裝GDB之前,首先要確實你的當前系統有沒有已經安裝:

# gdb -v
GNU gdb (Ubuntu 9.2-0ubuntu1~20.04) 9.2
Copyright (C) 2020 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.

如果出現上面的版本信息,如果GDB已經安裝好了;若沒有出現上面的信息,可以使用下面的命令直接安裝:

# apt-get install gdb  Debian系列作業系統安裝命令
# yum install gdb      RedHat系列作業系統安裝命令

Linux作業系統因為開源特性,很多作業系統都是基於開源版本不斷演化,發展成不同的版本和分支。但總的來說,可以分為三大系:Fedora系、Debian系和SlackWare系。

安裝成功後,再次使用# gdb -v 命令查看是否安裝成功,如果出現gdb的版本信息,說明軟體安裝成功。


使用yum或apt-get命令,從官方伺服器安裝的軟體包,一般都是穩定版,版本比較舊。如果想嘗鮮最先版本的GDB,可以使用源碼安裝。GDB因為是GNU開源工程,所以安裝步驟也是基本的三步:配置、編譯、安裝。

首先,要到GDB官網下載最新版本的源碼包:GDB源碼包官網地址

接下來,解壓這個源碼包,進入源碼包目錄,按照經典的三步走:配置、編譯、安裝即可。

# tar xvf gdb-10.1.tar.gz
# cd  gdb-10.1
# ./configure
# make
# make install
# gdb -v
GNU gdb (GDB) 10.1
Copyright (C) 2020 Free Software Foundation, Inc.
...



安裝好GDB後,接下來就要快速上手GDB的使用。GDB和shell類似,採用命令行形式的命令來調試程序,GDB常用的命令也就10來個,掌握了這些常用的調試命令,基本上就可以滿足日常程序的調試需求。


首先,要將需要調試的源程序編譯為可執行文件。以下面的C語言程序為例:

#include <stdio.h>

int main(void)
{
   int sum = 0;
   int i, num;
   
   printf("breakpoint 1\n");

   printf("input num: ");
   scanf("%d", &num);
   printf("breakpoint 2\n");

   if(num <= 0)
       printf("input invalid!\n");
   else
   {
       for(i = 1; i <= num; i++)
           sum += i;
       printf("sum = %d\n", sum);
   }

   printf("breakpoint 3\n");
   printf("goodbye!\n");
   return 0;
}

麻雀雖小,五臟俱全,上面的C語言程序實現了數據求和的簡單功能,但包含了程序的三種基本結構:順序程序結構、選擇程序結構和循環程序結構。為方便演示,我們分別在第8行、第12行、第23行設置了三個列印斷點的函數。接下來我們編譯這個程序:

# gcc -g -O0 main.c -o a.out

生成的可執行文件a.out裡都是二進位的機器指令,如果你想要源碼級調試,就需要在編譯程序時選中:debug選項(-g),生成的debug模式下的可執行文件a.out就包含了各種調試信息,其中最重要的一個信息就是:二進位機器指令和源程序代碼之間的對應關係,有了這個調試信息,當程序運行二進位機器指令的時候,就可以實時顯示對應的原始碼,更方便我們閱讀和調試。如果你在編譯的時候不使用debug模式,而使用release模式,那麼程序在運行時,顯示給你的就是二進位的機器代碼或彙編指令,不適合人類閱讀。

為提高程序的運行效率和性能,編譯器在編譯程序時,往往會對源程序進行優化,比如常量摺疊、緩存、內聯展開等。我們在編譯程序時,也可以通過參數來控制編譯優化級別,一般可分為如下等級:

-O0:不對程序進行編譯優化,默認的優化等級

-O1:可以減少目標文件的體積和程序執行時間

-O2:在-O1優化的基礎上,編譯器不執行循環展開和函數內聯,增加了代碼的性能

-Os:在-O2優化的基礎上,專門優化目標文件的大小

-O3:在-O2優化的基礎上,打開了-finline-functions, -funswitch-loops等標籤

源程序經過編譯器優化後,生成的二進位和原始碼之間可能就不是一一對應的關係了。為了更好的演示源碼級調試,我們在編譯時選擇-O0選項,不對程序進行編譯優化。


需要調試的可執行程序a.out生成以後,接下來就可以使用gdb進行調試了,可以使用下面的命令來進入GDB調試環境,調試a.out(編譯生成的a.out文件位於/home/gdb目錄下):

root@ubuntu:/home/gdb# gdb a.out 
GNU gdb (Ubuntu 9.2-0ubuntu1~20.04) 9.2
Copyright (C) 2020 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 "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
   <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from a.out...
(gdb) r
Starting program: /home/gdb/a.out
breakpoint 1
input num: 3
breakpoint 2
sum = 6
breakpoint 3
goodbye!
[Inferior 1 (process 2768) exited normally]
(gdb) q
root@ubuntu:/home/gdb#

當我們使用# gdb a.out時,就會進入交互式的gdb調試環境,運行run(可簡寫為 r)命令即可啟動a.out的運行。程序在運行過程中的輸出、輸入和正常運行模式下一樣,程序結束後,輸入quit(可簡寫為q)命令即可退出GDB調試環境,重新返回到SHELL環境下。


GDB作為一個調試器,調試器該有的功能他都有,比如:設置斷點、列印變量、單步等。我們在調試程序時,如果想讓程序在某行暫停,觀察此時的一些寄存器、變量值,此時可以通過GDB的斷點設置和變量列印功能來實現。

接下來就給大家演示下如何設置斷點和列印變量:

root@ubuntu:/home/gdb# gdb a.out 
GNU gdb (Ubuntu 9.2-0ubuntu1~20.04) 9.2
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from a.out...
(gdb) b 8
Breakpoint 1 at 0x11cb: file main.c, line 8.
(gdb) b 12
Breakpoint 2 at 0x1200: file main.c, line 12.
(gdb) b 23
Breakpoint 3 at 0x1252: file main.c, line 23.
(gdb) r
Starting program: /home/gdb/a.out

Breakpoint 1, main () at main.c:8
8     printf("breakpoint 1\n");
(gdb) print sum
$1 = 0
(gdb) c
Continuing.
breakpoint 1
input num: 3

Breakpoint 2, main () at main.c:12
12     printf("breakpoint 2\n");
(gdb) c
Continuing.
breakpoint 2
sum = 6

Breakpoint 3, main () at main.c:23
23     printf("breakpoint 3\n");
(gdb) print sum
$2 = 6
(gdb) c
Continuing.
breakpoint 3
goodbye!
[Inferior 1 (process 2780) exited normally]
(gdb) q
root@ubuntu:/home/gdb#

重新進入GDB調試環境,使用break(可簡寫為b)命令可以在原始碼的具體某一行設置斷點。設置好斷點後,使用run命令即可運行程序,程序在運行過程中遇到斷點會暫停下來,程序暫停後,你可以使用print命令來列印某一個具體變量的值。

如果想要程序繼續運行,可以使用continue命令(可簡寫為c),程序會繼續運行,直到遇到下一個斷點暫停下來。如果沒有再遇到斷點,程序則會一直執行下去,直到運行結束。

如果想要程序繼續運行,可以使用continue命令(可簡寫為c),程序會繼續運行,直到遇到下一個斷點暫停下來。如果沒有再遇到斷點,程序則會一直執行下去,直到運行結束。

在設置斷點的時候,如果想查看某一行代碼的具體行數,可以使用list(可簡寫為l)命令查看部分原始碼。多次輸入list命令,GDB就會依次顯示不同的代碼片段,直到你找到要設置的斷點的行數為止。

在GDB交互環境下,當你不輸入任何命令,直接敲擊回車鍵(Enter鍵)時,GDB會默認執行上一次你輸入的命令。所以,當你需要多次運行同一個命令時,不需要每次都輸入相同的命令,直接回車,就可以多次重複執行一個命令了。


GDB簡明教程後續部分,已經歸檔到個人博客:www.zhaixue.cc,可點擊左下角的:閱讀原文,繼續閱讀。




相關焦點

  • GDB入門教程之如何使用GDB啟動調試
    寫在前面:今天開始嘗試寫寫除Vim外的其他內容,仍然是以技術為主,可能涉及的內容包括Linux、正則表達式、gdb
  • 簡明 Python 教程:人生苦短,快用Python
    言歸正傳,我在國慶期間重溫了《簡明Python教程》,這是我認為最好的Python入門教程,作者和譯者的水準都非常高,舉重若輕,行雲流水,哪怕你沒有太豐富的編程經驗,你也可以在一到兩天內完全讀完它,並且能夠立即開始你的Python
  • GDB入門教程之查看變量
    return-1; } for(int i = 0; i < 256; ++i) { char_array[i] = 'a' + (i % 7); }一、查看普通變量基本類型變量、數組、字符串等可以使用 print 命令 (縮寫形式 p) 快速查看其在當前上下文中的值
  • 《料理模擬器》快速上手教程指南 怎麼快速入門?
    料理模擬器怎麼快速入門?想要自己經營好自己的小廚房,先要從基礎入門,有些萌新玩家還不知道怎麼操作,這裡給大家帶來了「獅子猿」提供的料理模擬器快速上手教程指南,一起來看下吧。 料理模擬器怎麼快速入門?
  • 吉他快速入門教程10分鐘學彈曲子
    吉他快速入門教程1,認識吉他吉他由琴軸,琴弦,品格,琴箱,琴碼,撥片等基本組成,琴軸主要起到調節琴弦音準的功能,琴箱主要起到擴音放音作用。吉他快速入門教程2,吉他演奏姿勢吉他的演奏姿勢分為坐式和立式,坐式要挺胸抬頭,右腿打在做腿上或者,或者將琴箱放在右腿上,琴橫向傾斜為45度角,左手為按弦,右手為撥弦,左手按弦為指尖觸弦,左手觸弦時候注意手指度不要碰到其他弦,以免造成其他弦發音不實影響音色,按弦的位置要按在兩個品之間。
  • Go 快速入門篇(三):單元測試、問題定位及代碼調試
    GoLand 單元測試失敗列印的錯誤信息非常簡潔,卻已經足夠讓開發者快速定位到問題代碼所在的文件和行數,從而在最短的時間內確認是單元測試的問題還是程序的問題。GDB 是一個由 GNU 開源組織發布的、Unix/Linux 作業系統下的、基於命令行的、功能強大的程序調試工具,Go 語言編譯後的二進位文件支持通過 GDB 進行調試,比如上篇教程通過 go build calc 編譯出來的可執行文件 calc,就可以直接用以下命令以調試模式運行:gdb calc
  • 資料| 簡明 Python 教程
    資料 | 簡明 Python 教程
  • revit軟體+30套入門教程+視頻講義
    今天給大家整理了2020 revit軟體+30套revit 入門教程+ revit 實戰 視頻講義,幫助大家更好地學習和掌握 revit知識與操作。快來收下吧。revit軟體+30套入門教程+視頻講義30套revit教程Revit 基本概念介紹Revit快捷鍵大全Revit與CAD的區別Revit可以做什麼?
  • AutoLine開源平臺簡明教程
    AutoLine開源平臺簡明教程AutoLine簡明教程常用cron表達式基本的使用過程每天凌晨1點執行一次更多的cron表達式用法 請直接看官方文檔吧,自己去找文檔AutoLine開源平臺發布AutoLine開源平臺安裝部署教程
  • 15個快速學習蘋果Swift程式語言的入門教程
    SWIFT特有許多其他的功能,使你的代碼更傳神:  閉包的統一與函數指針  元組和多個返回值  泛型  快速而簡潔的迭代範圍或集合  支持的方法,擴展的協議結構。  函數式編程模式,例如:地圖和過濾器今天為大家帶來15個快速學習蘋果Swift 語言的英文教程。簡單而實用。感興趣的可以去瞧瞧。
  • BIM全專業系列入門教程22套,帶你快速上手
    BIM全專業系列入門教程22套,帶你快速上手BIM技術是一種多維(三維空間、四維時間、五維成本、N維更多應用)模型信息集成技術,可以使建設項目的所有參與方(包括政府主管部門、業主、設計、施工、監理、造價等)在項目從概念產生到完全拆除的整個生命周期內都能夠在模型中操作信息和在信息中操作模型,從而從根本上改變從業人員依靠符號文字形式圖紙進行項目建設和運營管理的工作方式
  • 《簡明 Python 教程》微信版
    小編花了整整一天時間,終於把《簡明Python教程》整理到了公眾號裡。
  • 入門Python, 看這些資料就夠了
    要入門Python,資料並非越多越好, 基本上看這些資料就夠了。 。目錄:第一部分: Python入門&進階教程第二部分: Python Web框架第三部分: Python擴展資料推薦的學習路徑: 1. 使用實驗樓的開箱即用環境快速刷完Python3簡明教程,django基礎教程;2.
  • AutoCAD2021工作界面8菜單欄顯示與隱藏cad新手快速入門教程
    AutoCAD2021工作界面8菜單欄顯示與隱藏cad新手快速入門教程 2020-
  • 書聲琅琅:好的Python入門教程
    好的Python入門教程,書聲琅琅教育番茄老師微信pykf20介紹,python語言現在應用非常廣泛,不管是大數據還是人工智慧,應用最多的語言還是python,因此對於許多小白來講,看到python從業者的高薪資,想要轉行,或者致力於python開發的朋友,如果要學習python,從零基礎開始,一定需要一套完整的學習路線。
  • 一文學會revman軟體| Meta簡明教程(6)
    Meta簡明教程目錄5.Meta分析數據提取| Meta簡明教程(5)
  • 原來gdb的底層調試原理這麼簡單
    ptrace 系統函數是 Linux 內核提供的一個用於進程跟蹤的系統調用,通過它,一個進程(gdb)可以讀寫另外一個進程(test)的指令空間、數據空間、堆棧和寄存器的值。而且 gdb 進程接管了 test 進程的所有信號,也就是說系統向 test 進程發送的所有信號,都被 gdb 進程接收到,這樣一來,test 進程的執行就被 gdb 控制了,從而達到調試的目的。
  • 《火炬之光3》新手教程圖文全解析 怎麼快速入門?
    怎麼快速入門? 目錄 第1頁:劇情背景 第2頁:按鍵操作 第3頁:遊戲評測 第4頁:角色:鑄鐵戰士 第5頁:角色:幽暮法師 第6頁:角色:神槍手 第7頁:角色:軌道專家 展開更多+ 火炬之光3怎麼快速入門
  • 簡明Fastai入門教程(一)
    終於下定決心寫這篇教程了,之前偶然接觸到了Fastai這個框架,發現它完全是對新手友好的。
  • ASP.NET與MySQL資料庫簡明圖示入門教程
    安裝非常簡單,按照安裝步驟不會導致任何問題,如下圖:MySQLServer安裝MySQLServer安裝MySQLServer安裝ASP.NET與MySQL資料庫簡明圖示入門教程src="img2005/104888491.gif"align=centervspace=1border