精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

告別代碼Bug,GDB調試工具詳解

開發(fā) 開發(fā)工具
當我們在開發(fā)中遇到程序崩潰、結果異常等問題時,是不是常常感到無從下手?別擔心,今天要給大家介紹的 GDB 調試工具,就是我們戰(zhàn)勝這些 “小怪獸” 的有力武器,它能幫助我們深入程序內(nèi)部,揪出隱藏的 Bug,讓程序乖乖聽話。

在軟件開發(fā)的漫漫長路上,Bug 就像隱藏在黑暗中的 “小怪獸”,時不時跳出來給開發(fā)者們制造麻煩。曾經(jīng),歐洲航天局(ESA)首次發(fā)射阿麗亞娜 5 號火箭,這本是太空探索史上的重要時刻,卻因一行代碼導致災難性故障,價值近 5 億歐元的火箭在發(fā)射 37 秒后爆炸 。經(jīng)過調查,原來是制導系統(tǒng)存在軟件缺陷,一段源于阿麗亞娜 4號的死代碼中,64 位浮點變量轉換為 16 位帶符號整數(shù)時出現(xiàn)整數(shù)溢出問題,最終導致火箭自毀。這樣的故事告訴我們,一個看似不起眼的 Bug,可能會引發(fā)難以估量的后果。

當我們在開發(fā)中遇到程序崩潰、結果異常等問題時,是不是常常感到無從下手?別擔心,今天要給大家介紹的 GDB 調試工具,就是我們戰(zhàn)勝這些 “小怪獸” 的有力武器,它能幫助我們深入程序內(nèi)部,揪出隱藏的 Bug,讓程序乖乖聽話。

一、GDB是什么?

1.1GDB概述

GDB,全稱 GNU Debugger,是 GNU 開源組織發(fā)布的一款功能強大的程序調試工具。自 1986 年由理查德?斯托曼(Richard Stallman)編寫以來,它不斷發(fā)展和完善,如今已成為 Linux 系統(tǒng)下調試程序的首選工具 ,在整個 Linux 生態(tài)系統(tǒng)中占據(jù)著舉足輕重的地位。它就像是一位經(jīng)驗豐富的偵探,深入程序的 “案發(fā)現(xiàn)場”,幫助開發(fā)者們找到隱藏在代碼中的 “罪犯”——Bug。

GDB 支持多種編程語言,包括但不限于 C、C++、Fortran、Ada、Objective-C、Go、D 等,能夠與 GCC、Clang、LLVM 等一系列主流編譯器無縫集成。這意味著無論你使用哪種編程語言進行開發(fā),GDB 都能為你提供高效的調試支持,在桌面應用程序、服務器端服務,還是嵌入式系統(tǒng)的開發(fā)中,都能以其強大的功能和靈活的交互方式,為開發(fā)者提供無與倫比的調試體驗。

  • GDB官網(wǎng):https://www.gnu.org/software/gdb/(https://www.gnu.org/software/gdb/)
  • GDB適用的編程語言: Ada / C / C++ / objective-c / Pascal 等。
  • GDB的工作方式: 本地調試和遠程調試。

目前release的最新版本為8.0,GDB可以運行在Linux 和Windows 操作系統(tǒng)上。

1.2GDB 的優(yōu)勢

功能豐富:GDB 提供了全面的調試功能,如設置斷點(包括普通斷點、條件斷點)、單步執(zhí)行(step 和 next )、查看變量值(print)、觀察內(nèi)存(x 命令)、回溯函數(shù)調用棧(backtrace)等。這些功能可以幫助開發(fā)者深入分析程序的運行狀態(tài),快速定位問題。比如,在調試一個復雜的 C++ 程序時,我們可以通過設置條件斷點,當某個變量滿足特定條件時程序暫停,從而精準地捕捉到問題出現(xiàn)的時刻;利用回溯函數(shù)調用棧,清晰地了解函數(shù)的調用順序和各層調用間的上下文關系,快速定位問題發(fā)生在哪個函數(shù)調用鏈路中。

跨平臺支持:它支持廣泛的操作系統(tǒng)和平臺,包括 Linux、Windows(通過 MinGW 或 Cygwin)、macOS 以及多種嵌入式平臺(如 ARM、RISC-V 等)。無論你是在開發(fā)桌面應用、移動應用還是嵌入式系統(tǒng),GDB 都能發(fā)揮作用。在遠程調試時,GDB 非常靈活,可以與不同架構的系統(tǒng)進行連接,適用于跨平臺和多架構的調試。比如,開發(fā)一款同時在 Linux 和 Windows 系統(tǒng)上運行的軟件,使用 GDB 可以在不同系統(tǒng)下進行統(tǒng)一的調試操作,提高開發(fā)效率。

強大的擴展性:GDB 支持插件機制,可以通過安裝第三方插件增強其功能,如內(nèi)存分析、性能剖析、遠程調試等。用戶還可以通過 Python 腳本擴展 GDB 的功能,進行定制化調試操作。這對于需要在調試過程中進行復雜計算或自動化分析的場景非常有用。例如,在進行大規(guī)模數(shù)據(jù)處理程序的調試時,可以編寫 Python 腳本來自動化分析程序運行過程中產(chǎn)生的大量數(shù)據(jù),快速發(fā)現(xiàn)潛在問題。

開源免費:作為一款開源軟件,GDB 擁有龐大的社區(qū)支持,開發(fā)者們可以自由獲取、使用和修改它的源代碼。這不僅降低了開發(fā)成本,還使得 GDB 能夠不斷吸收社區(qū)的智慧和力量,持續(xù)進化和完善。同時,豐富的社區(qū)資源,如文檔、教程、論壇等,也為開發(fā)者們學習和使用 GDB 提供了便利。

與一些集成開發(fā)環(huán)境(IDE)自帶的調試工具相比,GDB 雖然沒有華麗的圖形界面,但它更加輕量級、靈活,且無依賴,不依賴于任何復雜的圖形界面或大型庫,這使得它非常適合在資源受限的環(huán)境中使用,比如嵌入式開發(fā) 。在服務器或遠程開發(fā)環(huán)境中,GDB 不需要圖形化界面,可以直接通過 SSH 連接到目標機器進行調試。而且,GDB 能夠提供比大多數(shù) IDE 更低級別的控制和調試能力,例如,它可以直接操作內(nèi)存、寄存器,甚至直接修改程序的執(zhí)行流,這對于一些高級調試需求至關重要。

二、GDB基礎操作

2.1安裝與啟動GDB

(1)安裝GDB

  • gdb -v 檢查是否安裝成功,未安裝成功則安裝(必須確保編譯器已經(jīng)安裝,如 gcc) 。
  • 啟動 gdb
  • gdb test_file.exe 來啟動 gdb 調試, 即直接指定需要調試的可執(zhí)行文件名
  • 直接輸入 gdb 啟動,進入 gdb 之后采用命令 file test_file.exe 來指定文件名
  • 如果目標執(zhí)行文件要求出入?yún)?shù)(如 argv[] 接收參數(shù)),則可以通過三種方式指定參數(shù):
  • 在啟動 gdb 時,gdb --args text_file.exe
  • 在進入gdb 之后,運行 set args param_1
  • 在 進入 gdb 調試以后,run param_1 或者 start para_1

(2)啟動 GDB

在使用 GDB 調試程序之前,我們需要先編譯程序并生成包含調試信息的可執(zhí)行文件。以 C 語言程序為例,使用 GCC 編譯器時,通過在編譯命令中添加 -g 參數(shù)來實現(xiàn),例如:

gcc -g -o my_program my_program.c

這樣生成的 my_program 可執(zhí)行文件就包含了調試所需的符號信息,這些符號信息就像是程序中的 “地圖標記”,能夠幫助 GDB 在調試時準確地定位到代碼中的變量、函數(shù)和行號等關鍵位置。

啟動 GDB 有多種方式,以下是幾種常見的方法:

調試新程序:最直接的方式是在終端中輸入 gdb 加上可執(zhí)行文件名,例如:

gdb my_program

這種方式適用于我們需要從程序的初始狀態(tài)開始調試,GDB 會加載程序的調試信息,并準備好接受調試命令。

附加到正在運行的進程:當程序已經(jīng)在運行,并且我們想要調試這個正在運行的實例時,可以使用 attach 命令。首先,通過 ps -ef | grep my_program 命令獲取程序的進程 ID(PID),然后使用以下命令將 GDB 附加到該進程:

gdb
(gdb) attach <PID>

這種方式在程序出現(xiàn)運行時錯誤,需要在不重啟程序的情況下進行調試時非常有用,它可以讓我們直接查看程序當前的運行狀態(tài),分析問題出現(xiàn)的原因 。

使用 core 文件調試:如果程序在運行過程中崩潰并生成了 core 文件(系統(tǒng)默認情況下可能不會生成 core 文件,需要通過 ulimit -c unlimited 命令設置允許生成 core 文件 ),我們可以使用 GDB 加載 core 文件進行調試。命令如下:

gdb my_program core

Core 文件就像是程序崩潰時的 “快照”,記錄了程序崩潰時的內(nèi)存狀態(tài)、寄存器值等關鍵信息,通過分析 core 文件,我們可以找到導致程序崩潰的原因,比如空指針引用、數(shù)組越界等問題。

2.2gdb的使用

運行程序

run(r)運行程序,如果要加參數(shù),則是run arg1 arg2 ...

查看源代碼

list(l):查看最近十行源碼
list fun:查看fun函數(shù)源代碼
list file:fun:查看flie文件中的fun函數(shù)源代碼

設置斷點與觀察斷點

break 行號/fun設置斷點。
break file:行號/fun設置斷點。
break if<condition>:條件成立時程序停住。
info break(縮寫:i b):查看斷點。
watch expr:一旦expr值發(fā)生改變,程序停住。
delete n:刪除斷點。

單步調試

continue(c):運行至下一個斷點。
step(s):單步跟蹤,進入函數(shù),類似于VC中的step in。
next(n):單步跟蹤,不進入函數(shù),類似于VC中的step out。
finish:運行程序,知道當前函數(shù)完成返回,并打印函數(shù)返回時的堆棧地址和返回值及參數(shù)值等信息。
until:當厭倦了在一個循環(huán)體內(nèi)單步跟蹤時,這個命令可以運行程序知道退出循環(huán)體。

查看運行時數(shù)據(jù)

print(p):查看運行時的變量以及表達式。
ptype:查看類型。
print array:打印數(shù)組所有元素。
print *array@len:查看動態(tài)內(nèi)存。len是查看數(shù)組array的元素個數(shù)。
print x=5:改變運行時數(shù)據(jù)。

2.3常用命令詳解

⑴設置斷點(break):斷點是調試中最常用的工具之一,它就像是在程序的執(zhí)行路徑上設置的 “路障”,當程序執(zhí)行到斷點處時會暫停,以便我們檢查程序的狀態(tài)。設置斷點的基本命令是 break,可以簡寫為 b。例如,要在 main 函數(shù)的入口處設置斷點,可以使用以下命令:

(gdb) b main

也可以在指定行號處設置斷點,假設我們的代碼文件是 my_program.c,要在第 20 行設置斷點,可以這樣操作:

(gdb) b my_program.c:20

此外,還可以設置條件斷點,只有當條件滿足時,斷點才會生效。比如,當變量 i 的值等于 10 時暫停程序:

(gdb) b my_program.c:30 if i == 10

⑵運行程序(run):設置好斷點后,使用 run 命令(簡寫為 r)來啟動程序。如果程序需要傳入命令行參數(shù),可以在 run 命令后面直接添加參數(shù),例如:

(gdb) run arg1 arg2

run 命令會使程序從起始位置開始執(zhí)行,直到遇到第一個斷點或者程序結束。

繼續(xù)運行(continue):當程序在斷點處暫停后,如果我們想讓程序繼續(xù)執(zhí)行,直到下一個斷點或程序結束,可以使用 continue 命令,簡寫為 c:

(gdb) c

這個命令非常實用,在我們檢查完當前斷點處的程序狀態(tài)后,繼續(xù)程序的執(zhí)行,以觀察后續(xù)的運行情況。

單步執(zhí)行(next、step)

next:next 命令(簡寫為 n)用于單步執(zhí)行程序,每次執(zhí)行一行代碼,但當遇到函數(shù)調用時,不會進入函數(shù)內(nèi)部,而是將函數(shù)調用視為一行代碼直接執(zhí)行過去。例如:

(gdb) n

假設我們有一個函數(shù)調用 result = add_numbers(a, b),使用 next 命令會直接執(zhí)行完這個函數(shù)調用,并停在下一行代碼,而不會進入 add_numbers 函數(shù)內(nèi)部查看其執(zhí)行過程。

step:step 命令(簡寫為 s)同樣是單步執(zhí)行,但當遇到函數(shù)調用時,會進入函數(shù)內(nèi)部,在函數(shù)的第一行代碼處暫停。比如:

(gdb) s

使用 step 命令遇到上述的 add_numbers 函數(shù)調用時,會進入 add_numbers 函數(shù)內(nèi)部,方便我們查看函數(shù)內(nèi)部的執(zhí)行邏輯,檢查每一步的變量變化和計算結果,對于調試函數(shù)內(nèi)部的問題非常有效。

⑸ 打印變量值(print):在調試過程中,我們經(jīng)常需要查看變量的值,這時就可以使用 print 命令(簡寫為 p)。例如,要查看變量 i 的值,可以使用以下命令:

(gdb) p i

如果變量是一個復雜的數(shù)據(jù)結構,比如結構體或對象,print 命令也能完整地顯示其成員信息。此外,還可以對表達式進行求值,例如:

(gdb) p a + b

這條命令會計算 a + b 的值并顯示出來。

查看斷點信息(info break):使用 info break 命令(簡寫為 i b)可以查看當前設置的所有斷點的信息,包括斷點的編號、位置、條件等。例如:

(gdb) i b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x00000000004005c8 in main at my_program.c:10
        breakpoint already hit 1 time
2       breakpoint     keep y   0x00000000004005e0 in main at my_program.c:20 if i == 10

通過這些信息,我們可以清楚地了解斷點的設置情況,方便對斷點進行管理,比如刪除或禁用某些斷點。

2.4程序錯誤

  • 編譯錯:編寫程序的時候沒有符合語言規(guī)范導致編譯錯誤。比如:語法錯誤。
  • 運行時錯誤:編譯器檢查不出這種錯誤,但在運行時候可能會導致程序崩潰。比如:內(nèi)存地址非法訪問。
  • 邏輯錯誤:編譯和運行都很順利,但是程序沒有干我們期望干的事情。

2.5gdb調試段錯誤

什么是段錯誤?段錯誤是由于訪問非法地址而產(chǎn)生的錯誤。

  • 訪問系統(tǒng)數(shù)據(jù)區(qū),尤其是往系統(tǒng)保護的內(nèi)存地址寫數(shù)據(jù)。比如:訪問地址為0的地址。
  • 內(nèi)存越界(數(shù)組越界,變量類型不一致等)訪問到不屬于當前程序的內(nèi)存區(qū)域。

gdb調試段錯誤,可以直接運行程序,當程序運行崩潰后,gdb會打印運行的信息,比如:收到了SIGSEGV信號,然后可以使用bt命令,打印棧回溯信息,然后根據(jù)程序發(fā)生錯誤的代碼,修改程序。

2.6.core文件調試

(1)core文件

在程序崩潰時,一般會生成一個文件叫core文件。core文件記錄的是程序崩潰時的內(nèi)存映像,并加入調試信息,core文件生成過程叫做core dump(核心已轉儲)。系統(tǒng)默認不會生成該文件。

(2)設置生成core文件

  • ulimit -c:查看core-dump狀態(tài)。
  • ulimit -c xxxx:設置core文件的大小。
  • ulimit -c unlimited:core文件無限制大小。

(3)gdb調試core文件

當設置完ulimit -c xxxx后,再次運行程序發(fā)生段錯誤,此時就會生成一個core文件,使用gdb core調試core文件,使用bt命令打印棧回溯信息。

三、GDB調試程序用法

一般來說,GDB主要幫忙你完成下面四個方面的功能:

啟動你的程序,可以按照你的自定義的要求隨心所欲的運行程序。2、可讓被調試的程序在你所指定的調置的斷點處停住。(斷點可以是條件表達式)3、當程序被停住時,可以檢查此時你的程序中所發(fā)生的事。4、動態(tài)的改變你程序的執(zhí)行環(huán)境。

從上面看來,GDB和一般的調試工具沒有什么兩樣,基本上也是完成這些功能,不過在細節(jié)上,你會發(fā)現(xiàn)GDB這個調試工具的強大,大家可能比較習慣了圖形化的調試工具,但有時候,命令行的調試工具卻有著圖形化工具所不能完成的功能。讓我們一一看來。

一個調試示例:

源程序:tst.c

1 #include <stdio.h>
2
3 int func(int n)
4 {
5 int sum=0,i;
6 for(i=0; i<n; i++)
7 {
8 sum+=i;
9 }
10 return sum;
11 }
12
13
14 main()
15 {
16 int i;
17 long result = 0;
18 for(i=1; i<=100; i++)
19 {
20 result += i;
21 }
22
23 printf("result[1-100] = %d /n", result );
24 printf("result[1-250] = %d /n", func(250) );
25 }

編譯生成執(zhí)行文件:(Linux下)

hchen/test> cc -g tst.c -o tst

使用GDB調試:

hchen/test> gdb tst <---------- 啟動GDB
GNU gdb 5.1.1
Copyright 2002 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-SUSE-linux"...
(gdb) l <-------------------- l命令相當于list,從第一行開始例出原碼。
1 #include <stdio.h>
2
3 int func(int n)
4 {
5 int sum=0,i;
6 for(i=0; i<n; i++)
7 {
8 sum+=i;
9 }
10 return sum;
(gdb) <-------------------- 直接回車表示,重復上一次命令
11 }
12
13
14 main()
15 {
16 int i;
17 long result = 0;
18 for(i=1; i<=100; i++)
19 {
20 result += i;
(gdb) break 16 <-------------------- 設置斷點,在源程序第16行處。
Breakpoint 1 at 0x8048496: file tst.c, line 16.
(gdb) break func <-------------------- 設置斷點,在函數(shù)func()入口處。
Breakpoint 2 at 0x8048456: file tst.c, line 5.
(gdb) info break <-------------------- 查看斷點信息。
Num Type Disp Enb Address What
1 breakpoint keep y 0x08048496 in main at tst.c:16
2 breakpoint keep y 0x08048456 in func at tst.c:5
(gdb) r <--------------------- 運行程序,run命令簡寫
Starting program: /home/hchen/test/tst

Breakpoint 1, main () at tst.c:17 <---------- 在斷點處停住。
17 long result = 0;
(gdb) n <--------------------- 單條語句執(zhí)行,next命令簡寫。
18 for(i=1; i<=100; i++)
(gdb) n
20 result += i;
(gdb) n
18 for(i=1; i<=100; i++)
(gdb) n
20 result += i;
(gdb) c <--------------------- 繼續(xù)運行程序,continue命令簡寫。
Continuing.
result[1-100] = 5050 <----------程序輸出。

Breakpoint 2, func (n=250) at tst.c:5
5 int sum=0,i;
(gdb) n
6 for(i=1; i<=n; i++)
(gdb) p i <--------------------- 打印變量i的值,print命令簡寫。
$1 = 134513808
(gdb) n
8 sum+=i;
(gdb) n
6 for(i=1; i<=n; i++)
(gdb) p sum
$2 = 1
(gdb) n
8 sum+=i;
(gdb) p i
$3 = 2
(gdb) n
6 for(i=1; i<=n; i++)
(gdb) p sum
$4 = 3
(gdb) bt <--------------------- 查看函數(shù)堆棧。
#0 func (n=250) at tst.c:5
#1 0x080484e4 in main () at tst.c:24
#2 0x400409ed in __libc_start_main () from /lib/libc.so.6
(gdb) finish <--------------------- 退出函數(shù)。
Run till exit from #0 func (n=250) at tst.c:5
0x080484e4 in main () at tst.c:24
24 printf("result[1-250] = %d /n", func(250) );
Value returned is $6 = 31375
(gdb) c <--------------------- 繼續(xù)運行。
Continuing.
result[1-250] = 31375 <----------程序輸出。

Program exited with code 027. <--------程序退出,調試結束。
(gdb) q <--------------------- 退出gdb。
hchen/test>

好了,有了以上的感性認識,還是讓我們來系統(tǒng)地認識一下gdb吧。

基本gdb命令:

GDB常用命令	格式	含義	簡寫
list	List [開始,結束]	列出文件的代碼清單	l
prit	Print 變量名	打印變量內(nèi)容	p
break	Break [行號或函數(shù)名]	設置斷點	b
continue	Continue [開始,結束]	繼續(xù)運行	c
info	Info 變量名	列出信息	i
next	Next	下一行	n
step	Step	進入函數(shù)(步入)	S
display	Display 變量名	顯示參數(shù)	 
file	File 文件名(可以是絕對路徑和相對路徑)	加載文件	 
run	Run args	運行程序	r

四、GDB進階功能

4.1回溯追蹤(backtrace)

在程序調試過程中,了解函數(shù)調用順序及各層調用間的上下文關系至關重要。有時候程序出現(xiàn)錯誤,但我們并不知道錯誤是在哪個函數(shù)調用鏈路中產(chǎn)生的,這時候回溯追蹤功能就派上用場了。GDB 提供了backtrace命令,簡寫為bt,用于展示當前的調用棧信息。

當程序運行出現(xiàn)異常或者在斷點處暫停時,輸入bt命令,GDB 會按深度由淺至深列出各個棧幀,每個棧幀包含了函數(shù)名、源文件名、行號及參數(shù)值等關鍵信息。例如,我們有一個包含多個函數(shù)調用的程序:

#include <stdio.h>

void function_c(int num) {
    int result = num * 2;
    printf("Function C: result = %d\n", result);
}

void function_b(int num) {
    function_c(num + 1);
}

void function_a() {
    int num = 5;
    function_b(num);
}

int main() {
    function_a();
    return 0;
}

在 GDB 中調試這個程序,當程序在function_c函數(shù)內(nèi)暫停時,輸入bt命令,輸出結果可能如下:

(gdb) bt
#0  function_c (num=6) at test.c:5
#1  0x000000000040056d in function_b (num=5) at test.c:9
#2  0x0000000000400588 in function_a () at test.c:13
#3  0x00000000004005a4 in main () at test.c:17

從輸出中可以清晰地看到函數(shù)的調用順序:main調用function_a,function_a調用function_b,function_b調用function_c,并且還能看到每個函數(shù)調用時的參數(shù)值 。這對于我們快速定位問題發(fā)生的位置非常有幫助,比如如果function_c中出現(xiàn)了除零錯誤,我們就可以通過回溯追蹤信息,從調用鏈路上查找傳入function_c的參數(shù)是如何計算得出的,進而找到問題的根源。

4.2動態(tài)內(nèi)存檢測

內(nèi)存泄漏、非法訪問等內(nèi)存問題是程序健壯性的隱形殺手,它們可能會導致程序運行一段時間后出現(xiàn)性能下降甚至崩潰。雖然有像 Valgrind 這樣專門的內(nèi)存分析工具,但 GDB 自身也具備一定的內(nèi)存檢測能力,尤其是結合 heap 插件,可以對程序的堆內(nèi)存使用情況進行初步排查。

首先,我們需要獲取并加載 heap 插件,假設插件文件為gdbheap.py,使用以下命令加載插件:

(gdb) source /path/to/gdbheap.py

然后,我們可以將 GDB 附加到正在運行的進程上(假設進程 ID 為<pid>),并使用插件提供的命令來查看堆內(nèi)存分配情況:

(gdb) attach <pid>
(gdb) monitor heap

執(zhí)行上述命令后,GDB 會顯示堆內(nèi)存的相關信息,比如內(nèi)存塊的數(shù)量、大小、分配狀態(tài)等。通過觀察這些信息,我們可以發(fā)現(xiàn)一些潛在的內(nèi)存問題。例如,如果發(fā)現(xiàn)有大量的小內(nèi)存塊被分配且長時間沒有釋放,可能存在內(nèi)存泄漏的風險;如果看到內(nèi)存塊的分配和釋放順序異常,可能存在非法內(nèi)存訪問的問題。

下面是一個簡單的示例,展示如何使用 GDB 和 heap 插件檢測內(nèi)存問題:

#include <stdio.h>
#include <stdlib.h>

int main() {
    int *ptr1 = (int *)malloc(10 * sizeof(int));
    int *ptr2 = (int *)malloc(20 * sizeof(int));
    free(ptr1);
    // 故意不釋放ptr2,制造內(nèi)存泄漏
    return 0;
}

在程序運行后,使用 GDB 和 heap 插件進行檢測,通過分析插件輸出的堆內(nèi)存信息,我們就有可能發(fā)現(xiàn)ptr2所指向的內(nèi)存沒有被釋放,從而定位到內(nèi)存泄漏問題。

4.3條件斷點與觀察點

條件斷點:在一些復雜的程序中,我們可能不希望程序在每個斷點處都暫停,而是希望當滿足特定條件時才暫停程序執(zhí)行,這時候就可以使用條件斷點。例如,在一個處理數(shù)組的程序中,我們懷疑當數(shù)組下標i大于數(shù)組大小時會出現(xiàn)數(shù)組越界問題,我們可以設置如下條件斷點:

(gdb) break array_processing_function if i >= array_size

這樣,只有當i大于或等于array_size時,程序才會在array_processing_function處暫停,大大提高了調試效率,避免了在無關斷點處頻繁暫停程序,讓我們能夠更精準地捕捉到問題出現(xiàn)的時刻 。

觀察點:觀察點(Watchpoint)用于監(jiān)控變量值的變化。當觀察的變量被修改時,GDB 會自動暫停程序,這對于追蹤難以復現(xiàn)的偶發(fā)問題尤為有用。比如,在一個多線程程序中,某個全局變量的值被意外修改,但我們不確定是哪個線程在什么情況下修改的,就可以為這個全局變量設置觀察點:

(gdb) watch global_variable

當global_variable的值發(fā)生改變時,程序會立即暫停,此時我們可以查看當前的線程狀態(tài)、調用棧等信息,來確定變量是如何被修改的,從而找到問題的根源。此外,還可以設置讀觀察點(rwatch)和讀寫觀察點(awatch),rwatch在變量被讀取時暫停程序,awatch在變量被讀取或修改時暫停程序,根據(jù)具體的調試需求選擇合適的觀察點類型 。

4.4遠程調試

在實際開發(fā)中,我們經(jīng)常會遇到需要調試部署在遠程服務器或嵌入式設備上的程序的情況,GDB 支持通過網(wǎng)絡進行遠程調試,這極大地簡化了跨設備調試的復雜性。

遠程調試的基本原理是在遠程設備上運行 GDB 的服務器端(gdbserver),并在本地 GDB 客戶端連接至服務器端。具體操作步驟如下:

⑴在遠程設備上:首先確保遠程設備上安裝了gdbserver,可以通過gdbserver --version命令檢查是否安裝。然后啟動gdbserver,并指定調試的程序和監(jiān)聽端口,例如:

gdbserver :<port> /path/to/remote_program

其中<port>是未被占用的端口號,可以根據(jù)實際情況任意指定,/path/to/remote_program是要調試的程序路徑。啟動成功后,gdbserver會監(jiān)聽指定端口,等待本地 GDB 客戶端連接。

在本地 GDB 客戶端:在本地啟動 GDB,并加載本地保存的與遠程程序相同的可執(zhí)行文件副本(確保編譯時帶有調試信息),然后使用target remote命令連接到遠程gdbserver:

gdb ./local_program
(gdb) target remote <remote_host>:<port>

<remote_host>是遠程設備的 IP 地址或主機名,<port>是在遠程設備上啟動gdbserver時指定的端口號。連接成功后,就可以像在本地調試程序一樣,在本地 GDB 客戶端使用各種調試命令,如設置斷點、單步執(zhí)行、查看變量值等,GDB 會通過網(wǎng)絡與遠程gdbserver通信,實現(xiàn)對遠程程序的調試 。

例如,在開發(fā)一款嵌入式系統(tǒng)程序時,我們可以在開發(fā)板(遠程設備)上運行gdbserver,在本地 PC 上使用 GDB 客戶端進行調試,通過這種方式,能夠在本地環(huán)境中方便地調試運行在遠程嵌入式設備上的程序,提高開發(fā)效率 。

五、實戰(zhàn)技巧

5.1利用 TUI 模式提升效率

GDB 的 TUI(Terminal User Interface,終端用戶界面)模式提供了一種基于文本交互和圖形用戶交互之間的折中方法,在調試過程中能顯著提升效率。在 TUI 模式中,GDB 將終端屏幕劃分為源文本窗口和控制臺窗口,讓我們可以直觀地看到代碼的執(zhí)行情況 。

啟動 TUI 模式非常簡單,只需在啟動 GDB 時加上 -tui 參數(shù)即可。例如:

gdb -tui my_program

如果已經(jīng)在普通 GDB 模式下,還可以通過快捷鍵 Ctrl + X + A 來切換到 TUI 模式,再次按下該快捷鍵則可以返回普通模式。

進入 TUI 模式后,我們可以使用一系列快捷鍵和命令來進行調試操作。比如,使用 n(next)命令單步執(zhí)行代碼時,源文本窗口會實時高亮顯示當前執(zhí)行的代碼行,同時控制臺窗口會輸出執(zhí)行結果;設置斷點時,斷點所在的行號前會顯示特殊標記,方便我們識別和管理斷點。

在調試一個復雜的 C++ 項目時,我需要在多個函數(shù)之間來回切換查看代碼執(zhí)行邏輯,TUI 模式讓我可以直接在源文本窗口中清晰地看到代碼的上下文關系,配合單步執(zhí)行和斷點設置,快速定位到了程序中的邏輯錯誤。而且,當程序暫停時,按下 Ctrl + X + S 快捷鍵后,就可以直接使用 GDB 命令,而無需每次都回車確認,進一步提高了調試效率 。

5.2自定義命令與腳本自動化

在日常調試工作中,我們經(jīng)常會重復執(zhí)行一些相同的命令序列,比如每次調試時都需要設置相同的斷點、查看特定變量的值等。為了提高調試效率,GDB 允許我們將這些常用命令定義成自定義命令或腳本。

自定義命令的定義格式如下:

define command_name
    statement1
    statement2
   ...
end

其中,command_name 是自定義命令的名稱,statement 是具體的 GDB 命令。例如,我們可以定義一個名為 my_debug 的自定義命令,用于設置多個斷點并啟動程序:

define my_debug
    b main
    b function_a
    b function_b
    r
end

定義好自定義命令后,在 GDB 中直接輸入命令名即可執(zhí)行這些命令。

對于更復雜的操作,我們可以編寫 GDB 腳本。GDB 腳本是一個包含一系列 GDB 命令的文本文件,其擴展名為 .gdb 。例如,我們創(chuàng)建一個名為 debug_script.gdb 的腳本文件,內(nèi)容如下:

b main
b function_c if i > 10
r

在 GDB 中使用 source 命令加載腳本:

(gdb) source debug_script.gdb

這樣,腳本中的命令就會依次執(zhí)行。GDB 還提供了豐富的流程控制命令,如 if...else...end、while...end 等,結合這些命令,我們可以編寫功能強大的自動化調試腳本,實現(xiàn)復雜的調試邏輯。在調試一個大型數(shù)據(jù)庫應用程序時,我編寫了一個腳本,通過循環(huán)遍歷數(shù)據(jù)庫連接池中的連接對象,檢查每個連接的狀態(tài)和屬性,快速發(fā)現(xiàn)了連接泄漏和配置錯誤的問題,大大節(jié)省了調試時間 。

5.3配合 IDE 使用

雖然 GDB 本身是一個強大的命令行調試工具,但它也可以與一些集成開發(fā)環(huán)境(IDE)配合使用,充分發(fā)揮兩者的優(yōu)勢。以 Eclipse CDT 為例,它提供了直觀的圖形化界面,方便我們進行代碼編輯、項目管理和調試操作,同時又集成了 GDB 的強大調試功能。

在 Eclipse CDT 中使用 GDB 進行調試,首先需要創(chuàng)建一個 C/C++ 項目,并確保項目的編譯設置中包含調試信息(通常在項目屬性的 C/C++ Build - Settings 中,選擇 Debug 配置,勾選 Generate debug info 選項)。然后,在項目的源代碼中設置斷點,點擊 Eclipse 工具欄上的調試按鈕,Eclipse 會自動啟動 GDB,并將其與項目關聯(lián)起來。

在調試過程中,我們可以在 Eclipse 的調試視圖中查看變量值、調用棧信息,進行單步執(zhí)行、繼續(xù)執(zhí)行等操作,這些操作都通過 Eclipse 的圖形界面完成,但底層實際上是由 GDB 來執(zhí)行的。這種方式既保留了 GDB 的強大功能,又提供了更加便捷和直觀的調試體驗,對于新手開發(fā)者來說尤其友好,能夠快速上手調試工作。

責任編輯:武曉燕 來源: 深度Linux
相關推薦

2022-07-25 07:57:19

工具代碼調試

2025-07-03 02:00:00

2020-06-15 08:39:41

調試工具

2015-08-14 09:21:09

gdb工具調試 Go

2021-03-15 06:23:40

GDB調試代碼編程語言

2016-03-29 10:32:34

2021-07-28 08:53:53

GoGDB調試

2022-08-28 10:36:53

調試工具通用

2020-02-25 14:38:05

代碼開發(fā)工具

2010-06-04 17:48:20

Linux編程工具

2011-08-15 17:38:48

iPhone開發(fā)調試工具

2024-01-24 13:22:40

Python調試工具技巧

2024-07-09 08:31:26

2023-03-29 08:18:16

Go調試工具

2009-10-22 13:02:47

SQL SERVER

2016-12-02 20:23:51

AndroidADB

2012-02-24 09:25:20

JavaScript

2021-10-14 10:05:17

開源項目代碼

2010-06-04 16:07:09

Linux 性能測試工

2012-02-09 09:35:46

NUnit
點贊
收藏

51CTO技術棧公眾號

国产精品久久久久久久av电影| 日韩电影免费观看中文字幕| 91国在线高清视频| 天天操天天干天天插| 老牛影视一区二区三区| 日韩亚洲欧美中文在线| 亚洲女则毛耸耸bbw| 91精品产国品一二三产区| 国产精品久久久久久久岛一牛影视| 亚洲一区二区三区乱码aⅴ| 国产无码精品久久久| 北条麻妃国产九九九精品小说| 69久久99精品久久久久婷婷| 欧美大片在线播放| caoporn97在线视频| 久久午夜羞羞影院免费观看| 91久久久亚洲精品| 日本在线播放视频| 亚洲欧美文学| 色婷婷综合久久久久| 白丝女仆被免费网站| 国产亚洲字幕| 欧美性大战久久久久久久 | 91大神xh98hx在线播放| av亚洲精华国产精华精| 亚洲一区二区三| 在线观看av大片| 久久久久久久高潮| 韩日欧美一区二区| 免费网站看av| 欧美成人久久| 久久精品在线播放| 欧美激情 一区| 久久99视频| 亚洲国产精彩中文乱码av在线播放| 欧美日韩理论片| 国产成+人+综合+亚洲欧美| 欧美色道久久88综合亚洲精品| 激情五月六月婷婷| 激情影院在线观看| 最新国产精品久久精品| 中文字幕中文字幕在线中心一区| 都市激情一区| 欧美激情综合五月色丁香小说| 久久久99爱| 香蕉视频911| 91女厕偷拍女厕偷拍高清| 国产尤物99| 日本精品一区二区在线观看| 成人久久视频在线观看| 国产成人成网站在线播放青青 | 色婷婷综合久久久中字幕精品久久| 亚洲高清在线视频| 日本黄大片在线观看| 欧美寡妇性猛交xxx免费| 一区二区在线观看av| 国产内射老熟女aaaa| 69成人在线| 一区二区免费看| 免费视频爱爱太爽了| www.8ⅹ8ⅹ羞羞漫画在线看| 亚洲成人综合视频| 狠狠97人人婷婷五月| 成人午夜视屏| 欧美色涩在线第一页| 欧美伦理片在线观看| 亚洲日本免费电影| 日韩一区二区电影在线| 日本美女视频网站| 天天躁日日躁狠狠躁欧美巨大小说| 亚洲欧美一区二区三区在线| 精品成人无码一区二区三区| 国产精品国产三级国产在线观看| 欧美成人合集magnet| 国产在线视频你懂的| 亚洲免费大片| 国产精品视频一区二区高潮| 一区二区三区精彩视频| 国产suv精品一区二区883| 国产一区二区三区黄| 免费在线黄色网址| 亚洲欧洲制服丝袜| 欧美精品自拍视频| 日本.亚洲电影| 欧美一级久久久久久久大片| 国产又粗又长又爽| 成人影院天天5g天天爽无毒影院| 久久综合久久八八| 国产精品人人人人| 久久国产精品99久久久久久老狼| 91精品久久香蕉国产线看观看| 人妻无码一区二区三区久久99| 久久久欧美精品sm网站| www.午夜色| 欧美aa在线观看| 欧美人与z0zoxxxx视频| 性久久久久久久久久久| 久久精品久久久| 欧美一乱一性一交一视频| 91九色蝌蚪91por成人| bt7086福利一区国产| 亚洲一区二区三区乱码| 美女高潮在线观看| 5566中文字幕一区二区电影| 免费成人深夜夜行p站| 久久精品青草| 国产脚交av在线一区二区| 精品毛片在线观看| 国产精品伦理一区二区| www.玖玖玖| 91午夜精品| 亚洲小视频在线观看| 欧美日韩中文视频| 国内精品免费**视频| 麻豆91av| av免费不卡国产观看| 欧美高清视频不卡网| 小早川怜子久久精品中文字幕| 韩日在线一区| 91手机在线播放| 午夜免费视频在线国产| 一本高清dvd不卡在线观看| av漫画在线观看| 亚洲国产精品日韩专区av有中文 | 日本a级c片免费看三区| 丁香桃色午夜亚洲一区二区三区| 在线精品日韩| 福利精品一区| 国产一区二区三区久久精品| 成人免费区一区二区三区| 国产一区不卡精品| 亚洲国产欧洲综合997久久| 惠美惠精品网| 日韩精品视频免费在线观看| 国产性xxxx高清| 成人免费电影视频| 日韩欧美不卡在线| 伊人久久噜噜噜躁狠狠躁| 久久久www成人免费精品张筱雨| 国产精品xxxxxx| 久久精品亚洲一区二区三区浴池 | 美女视频一区二区三区| 欧美日韩亚洲一区二区三区在线观看| 国产拍在线视频| 亚洲国产又黄又爽女人高潮的| 精品一区在线视频| 成人精品鲁一区一区二区| 毛片av在线播放| 成人av资源网址| 久久免费高清视频| www.成人精品| 激情亚洲一区二区三区四区 | 欧美精品videos| 高h震动喷水双性1v1| 亚洲国产综合在线| 中文字幕人妻一区二区三区| 国产欧美综合一区二区三区| 精品一区二区国产| 国产日韩另类视频一区| 一区二区三区美女xx视频| 国产精品成人久久久| 国产精品每日更新| 成人一区二区三区仙踪林| 激情婷婷亚洲| 久久久久久久有限公司| 日韩av中字| 日韩最新av在线| 国产黄a三级三级三级| 天天色天天爱天天射综合| 一本色道久久综合亚洲精品图片 | 亚洲3atv精品一区二区三区| 添女人荫蒂视频| 日本欧美一区二区在线观看| 在线观看免费黄色片| 美女呻吟一区| 国产成人一区二| 成人在线观看免费网站| 精品国产乱码久久久久久夜甘婷婷 | 日韩在线黄色| 国产精品日日做人人爱 | 欧美在线一区二区三区四| 国产原创av在线| 日韩午夜av电影| 国产精品男女视频| 自拍偷拍国产精品| 亚洲av成人无码一二三在线观看| 日韩专区一卡二卡| 日本丰满大乳奶| 国产成人1区| 动漫精品视频| 91p九色成人| 国a精品视频大全| 2019中文字幕在线视频| 日韩免费电影网站| 一级久久久久久| 亚洲一区二区三区四区五区中文| 欧美老熟妇乱大交xxxxx| 国内精品久久久久影院薰衣草 | 国产综合久久久久影院| 精品这里只有精品| 在线看片不卡| 欧美在线一二三区| 99re8这里有精品热视频免费 | 99国产精品免费网站| 国产精品免费观看在线| а√天堂中文资源在线bt| 精品国产一区二区三区久久久狼| 日本v片在线免费观看| 日韩视频免费观看高清完整版| 伊人久久久久久久久久久久| 一区二区三区四区在线| 天美传媒免费在线观看| 久久综合色综合88| 熟女人妻一区二区三区免费看| 免费观看成人av| 成人在线激情网| 在线亚洲一区| 成人免费视频91| 欧美日韩四区| 日韩中文在线字幕| 国产精品久久天天影视| 日本一区二区免费看| 香蕉久久99| 加勒比在线一区二区三区观看| va天堂va亚洲va影视| 国产精品专区第二| 成人高清一区| 国产精品九九久久久久久久| 亚洲电影观看| 欧美亚洲另类制服自拍| √最新版天堂资源网在线| 久久99亚洲热视| a级在线观看| 欧美日韩成人网| www免费视频观看在线| 久久精品国产亚洲| 国产在线1区| 久久精品2019中文字幕| 色大18成网站www在线观看| 主播福利视频一区| av电影在线观看| 久久精品99久久香蕉国产色戒| 91精品国产91久久久久游泳池| 国产亚洲日本欧美韩国| 777电影在线观看| 久久九九热免费视频| 国产乱色在线观看| 九九精品视频在线| 四季久久免费一区二区三区四区| 欧美另类第一页| 大香伊人久久| 91av视频在线| 欧洲亚洲两性| 成人国内精品久久久久一区| 精品国产亚洲一区二区三区| 91超碰rencao97精品| a看欧美黄色女同性恋| 精品在线视频一区二区三区| 免费观看久久av| 亚洲va韩国va欧美va精四季| 999视频精品| 妺妺窝人体色www看人体| 亚洲美女色禁图| 亚洲视频在线a| 精品无人码麻豆乱码1区2区| 精品国产免费久久久久久婷婷| 成人av网站在线| 精品无码在线观看| 亚洲三级在线看| 日韩欧美一区二区一幕| 色婷婷综合久久久中文字幕| ,一级淫片a看免费| 精品国内片67194| 黄色网址在线播放| 伦理中文字幕亚洲| 综合另类专区| 91日韩在线播放| 天堂俺去俺来也www久久婷婷| 日韩免费毛片| 欧美精选在线| 99re在线视频免费观看| 激情六月婷婷久久| 波多野结衣影院| 综合电影一区二区三区| 国产精品7777777| 欧美日韩国产精品自在自线| 欧美一级特黄aaaaaa| 爽爽爽爽爽爽爽成人免费观看| 欧美性爽视频| 国产日韩在线精品av| 9l视频自拍蝌蚪9l视频成人| 日本不卡二区| 黑人一区二区| 亚洲免费黄色录像| 久久人人超碰精品| 免费在线观看黄色av| 欧美视频日韩视频| 无码国产精品一区二区免费16| 亚洲人成五月天| 草美女在线观看| 91精品中文在线| 国产探花一区二区| www.99热这里只有精品| 国内国产精品久久| 亚洲AV无码成人精品区明星换面| 亚洲成人资源在线| 国产成人免费看一级大黄| 中文字幕亚洲欧美日韩高清| 春色校园综合激情亚洲| 7777精品伊久久久大香线蕉语言| 成人一二三区| 国产男女激情视频| 99精品国产视频| 麻豆chinese极品少妇| 欧美日韩精品电影| 国产日本在线视频| 97在线视频免费观看| 亚洲网一区二区三区| 在线综合视频网站| 日本sm残虐另类| 午夜一区二区三区免费| 亚洲成人动漫av| 性网爆门事件集合av| 精品精品国产国产自在线| 日韩精品一区二区三区| 精品国产乱码一区二区三区四区| 欧美日韩综合| 日本在线视频播放| 亚洲男女毛片无遮挡| 91精品国自产| 久久精品亚洲一区| 亚州精品国产| 中文字幕中文字幕一区三区| 九一九一国产精品| 人人澡人人澡人人看| 欧美群妇大交群的观看方式| 在线观看完整版免费| 国产欧美一区二区三区四区| 成人综合久久| 99re6在线观看| 亚洲另类在线一区| 亚洲va欧美va| 久久频这里精品99香蕉| 都市激情亚洲欧美| 91专区在线观看| 91免费视频网| 亚洲欧美日韩激情| 夜夜嗨av一区二区三区免费区 | 欧美一区二区三区免费在线看| 日本福利在线| 96pao国产成视频永久免费| 亚洲精品国产首次亮相| 国产成人av免费观看| 亚洲午夜电影网| 日韩av成人| 国产精品嫩草视频| 亚洲精品久久久| 亚洲v在线观看| 欧美性xxxxhd| www.成人.com| 92看片淫黄大片欧美看国产片| 国产综合视频| 日韩精品电影一区二区| 欧美少妇bbb| 性欧美videoshd高清| 精品视频导航| 免费成人av资源网| 欧美日韩在线视频免费播放| 亚洲精品一区二区三区香蕉| 樱花草涩涩www在线播放| 日本成人三级电影网站| 激情综合色播激情啊| 国产91av视频| 永久免费精品影视网站| 日韩精品成人| 欧美日韩在线成人| 亚洲精品乱码久久久久久久久| 人人妻人人澡人人爽久久av| 国产精品444| 欧美暴力喷水在线| 久久久久亚洲av无码专区桃色| 欧美日韩激情一区| av中文资源在线资源免费观看| 色综合久久av| 成人精品免费看| 亚洲一区二区激情| 91精品国产91久久久久| 日韩电影二区| 亚洲男女在线观看| 欧美精品电影在线播放| 欧美调教sm| 视频一区二区视频| 免费看日批视频| 日韩一区二区三区四区| 麻豆理论在线观看| 中文字幕日韩精品久久| 91在线丨porny丨国产| 99国产成人精品| 国产99久久精品一区二区| 午夜亚洲福利|