精品欧美一区二区三区在线观看 _久久久久国色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技術棧公眾號

欧美中文字幕一区| 国产精品自拍电影| 成人在线免费| 亚洲欧美日本韩国| 久久国产主播精品| 一区二区日韩在线观看| 在线精品一区| 日韩一区二区三区xxxx| 小毛片在线观看| 色狠狠一区二区三区| 亚洲大片精品永久免费| 亚洲欧洲久久| 西西人体44www大胆无码| 久久国产尿小便嘘嘘| 国内精品久久久久久影视8| 我不卡一区二区| 欧美不卡在线观看| 欧美色精品在线视频| 国产精品无码一区二区在线| 黄色网址在线免费| 国产日韩欧美在线一区| 国产精品久久久久久久久久直播| 一区二区自拍偷拍| 亚欧美中日韩视频| 久久久久久久久久久人体| 免费黄色片网站| 国内自拍欧美| 日韩欧美激情四射| 欧美xxxxxbbbbb| 精品美女一区| 91精品福利在线| 阿v天堂2017| 美女精品导航| 夜夜操天天操亚洲| 91国在线高清视频| 成人日日夜夜| 日韩一区欧美小说| 亚洲高清不卡一区| 久草在现在线| 2021久久国产精品不只是精品| 国产成人精品福利一区二区三区| 99在线观看免费| 国产一区二区三区国产| 国产东北露脸精品视频| 欧美劲爆第一页| 青青草手机在线观看| 欧美96在线丨欧| 欧美成人精品影院| 精品99久久久久成人网站免费| 一个色综合网| 久久精品国产91精品亚洲| 免费一级suv好看的国产网站| 国产一区日韩| 色老头一区二区三区| 中文字幕求饶的少妇| 99精品网站| 精品精品国产国产自在线| 天堂av免费在线| 99视频精品全部免费在线视频| 色综合亚洲精品激情狠狠| 亚洲欧美综合7777色婷婷| 日韩欧美在线中字| 久久视频国产精品免费视频在线| 成人在线观看高清| 国内精品亚洲| 51午夜精品视频| 波多野结衣电影在线播放| 免费观看在线色综合| 国产伦精品免费视频| 国产三级第一页| 高清成人在线观看| 久久青青草综合| 啊v视频在线| 亚洲免费伊人电影| 鲁一鲁一鲁一鲁一色| 日韩免费小视频| 欧美一级欧美三级| 熟女丰满老熟女熟妇| 欧美日韩国产在线观看网站| 久久久久北条麻妃免费看| 久久久久久久久久久97| 亚洲一区二区免费看| 国产精品爽黄69| 亚洲av无码乱码国产精品久久| 91丨九色丨蝌蚪富婆spa| 五月天久久狠狠| 牛牛在线精品视频| 卡一卡二国产精品| 日韩一区二区中文字幕| 亚洲精品手机在线观看| 96sao在线精品免费视频| 亚洲国产天堂久久国产91 | 亚洲精品狠狠操| 国产一二三四区在线| 欧美一区二区三区久久精品茉莉花| 欧美黄色三级网站| 五月天婷婷导航| 国产精一区二区三区| 免费影院在线观看一区| 哥也色在线视频| 色婷婷av一区| 99免费观看视频| 久久亚洲成人| 欧美中文字幕在线视频| 国产肥老妇视频| 欧美国产综合色视频| 国产精彩视频一区二区| 日本亚洲欧洲无免费码在线| 亚洲精品不卡在线| 特级片在线观看| 日本视频在线一区| 久久久com| 日本大胆在线观看| 91福利国产成人精品照片| 免费成年人高清视频| 亚洲深夜福利在线观看| 欧美黄色性视频| 91国产精品一区| 久久精品水蜜桃av综合天堂| 今天免费高清在线观看国语| 草莓视频成人appios| 精品一区二区三区三区| 久热精品在线观看| 国产成人在线免费| 欧美日韩亚洲国产成人| 国产成人a视频高清在线观看| 日韩激情av在线播放| 亚洲精品午夜久久久久久久| 国产精品亚洲人在线观看| 一本一生久久a久久精品综合蜜| 日韩欧美一区二区三区在线观看| 亚洲国产日韩精品在线| 欧美片一区二区| 中文字幕一区二区免费| 成人激情午夜影院| 成人av在线播放观看| 精品久久亚洲| 久久综合色88| 国产精品伊人久久| 亚洲婷婷综合久久一本伊一区 | 麻豆精品视频在线观看| 视频一区亚洲| 成人国产精品| 最近2019免费中文字幕视频三| 懂色av蜜臀av粉嫩av喷吹| 欧美激情中文不卡| 91极品尤物在线播放国产| 欧洲乱码伦视频免费| 国产精品第一第二| 9191在线观看| 91精品国产欧美日韩| 成年人av电影| 成人亚洲一区二区一| 成人黄色大片网站| 日韩影视在线观看| 国产成人精品一区二区三区| 国产精品视频二区三区| 欧美吞精做爰啪啪高潮| fc2ppv在线播放| 国产一区二区91| 国产一线二线三线女| 亚洲欧洲av| 国产精品电影观看| 国产欧美黑人| 亚洲成年人影院在线| 国产污视频在线看| 2021中文字幕一区亚洲| 最近中文字幕一区二区| 亚洲成人一区| 狠狠干一区二区| 日韩欧美精品电影| 久久精品视频va| 丰满人妻一区二区三区免费| 精品欧美国产一区二区三区| 国产小视频自拍| 久久99国内精品| 久操网在线观看| 欧美日韩国产免费观看视频| 亚洲综合色av| 美女写真久久影院| 国产欧美日韩另类一区| 成人黄色免费看| av网站大全在线| 日韩精品在线视频观看| 91国偷自产中文字幕久久| 亚洲国产综合人成综合网站| 手机免费看av| 国产剧情av麻豆香蕉精品| 国产亚洲综合视频| 91精品啪在线观看国产81旧版| 国产精品久久久久久久久久久久午夜片 | 国产免费999| 欧美成人日韩| 日韩福利视频| 国产精品丝袜在线播放| 国产精品在线看| 欧美久久天堂| 操日韩av在线电影| 国产精品扒开腿做爽爽爽男男| 亚洲人妻一区二区| 欧美日韩国产免费| 国产精品成人网站| 国产精品久线在线观看| 国产熟女高潮一区二区三区| 久久av中文字幕片| 国产日韩一区二区在线| 欧美有码视频| 亚洲一区二区三区精品视频| 麻豆国产欧美一区二区三区r| 国产在线精品成人一区二区三区| 日本蜜桃在线观看视频| 久热在线中文字幕色999舞| 国产中文字幕在线观看| 亚洲成人激情在线观看| 国产三级第一页| 欧美日韩中文字幕一区二区| 在线观看免费av片| 午夜视频一区在线观看| 青青草手机在线视频| 国产精品欧美综合在线| www.久久国产| 成人av一区二区三区| 三级黄色片播放| www.xxxx日本| 高清av一区二区| 毛毛毛毛毛毛毛片123| 青青草国产精品97视觉盛宴| 欧美a在线视频| 日韩视频一区| 青草青青在线视频| 国产伊人精品| 日本老太婆做爰视频| 99久久99热这里只有精品| 日韩理论片在线观看| 欧美美女在线| 蜜桃av久久久亚洲精品| 网红女主播少妇精品视频| 国产日产精品一区二区三区四区| 136导航精品福利| 99久久99久久精品国产片| 日韩中文字幕无砖| 福利视频久久| 成人搞黄视频| 激情小说综合网| 欧美亚洲tv| 欧美lavv| 日韩精品久久| 在线不卡日本| 欧美粗暴jizz性欧美20| 久久久国内精品| 99在线精品视频在线观看| 狠狠97人人婷婷五月| 久久福利影视| 欧美一级裸体视频| 精品在线你懂的| www.桃色.com| 国产不卡视频在线播放| www.黄色网| 99综合电影在线视频| 18禁裸乳无遮挡啪啪无码免费| 久久久精品免费免费| 特黄一区二区三区| 亚洲一区二区av在线| 国产精品男女视频| 欧美性高清videossexo| 国产口爆吞精一区二区| 欧美成人video| 四虎国产精品永远| 色噜噜狠狠狠综合曰曰曰88av| av片在线观看免费| 午夜免费日韩视频| 欧美色片在线观看| 亚洲999一在线观看www| 久久中文字幕导航| 少妇特黄a一区二区三区| 欧美在线网站| 超碰日本道色综合久久综合 | 国产精品护士白丝一区av| h色网站在线观看| 精品久久久久久| 中文字幕 人妻熟女| 日韩一区二区视频| 你懂的好爽在线观看| 爽爽爽爽爽爽爽成人免费观看| 18videosex性欧美麻豆| 2019中文字幕在线免费观看| 国产精品第一| 精品国产一区二区三区久久久久久 | 日韩成人伦理电影在线观看| 国产精品igao网网址不卡| 91网页版在线| 国产一区二区视频在线观看免费| 懂色av一区二区三区| 国产精品主播一区二区| 亚洲美女在线看| 97caopor国产在线视频| 国产激情综合五月久久| av成人男女| 中文网丁香综合网| 午夜在线精品偷拍| 潘金莲一级淫片aaaaa| 中日韩av电影| 国产一级片毛片| 日韩视频一区二区在线观看| 国产美女性感在线观看懂色av| 欧美激情第6页| 亚洲精品一区av| 四虎永久国产精品| 香蕉国产精品偷在线观看不卡| 日本黄色三级网站| 国产精品激情偷乱一区二区∴| 亚洲黄网在线观看| 亚洲国产成人在线播放| 91极品在线| 成人国产在线视频| 日韩中文在线电影| 91av俱乐部| 26uuu国产一区二区三区| 免费无码毛片一区二区app| 欧美日本高清视频在线观看| 黄色大片在线免费观看| 69精品小视频| 国产精品99久久免费观看| 久久久久久av无码免费网站下载| 久久精品亚洲一区二区| 污片免费在线观看| 亚洲大尺度视频在线观看| 亚洲黄色小说网| 久国内精品在线| 欧美视频二区欧美影视| 中文字幕免费高| 韩国女主播成人在线观看| 色婷婷精品国产一区二区三区| 午夜不卡影院| 91夜夜未满十八勿入爽爽影院| 日韩av片子| av亚洲天堂网| 国产精品国产自产拍高清av王其| 最近国语视频在线观看免费播放| 亚洲欧洲成视频免费观看| 成人性生交大片免费网站| 欧美极品一区二区| 天堂一区二区在线免费观看| 一区二区伦理片| 欧美人xxxx| 成人毛片av在线| 91精品黄色| 在线 亚洲欧美在线综合一区| 2一3sex性hd| 色一情一伦一子一伦一区| aaa在线观看| 成人免费视频a| 欧美在线不卡| 亚洲调教欧美在线| 91久久免费观看| 精品美女在线观看视频在线观看| 亚洲伊人一本大道中文字幕| 国产综合激情| 黄色正能量网站| 欧美色涩在线第一页| 草莓福利社区在线| 久久99精品久久久久久秒播放器| 亚洲欧美日韩专区| 林心如三级全黄裸体| 欧美变态凌虐bdsm| 亚洲私拍视频| 一区二区三区的久久的视频| 国产成人免费视频网站| 国产一区二区99| 日日摸夜夜添一区| 538任你躁精品视频网免费| 国产 福利 在线| 国产精品三级视频| 亚洲男女视频在线观看| 欧美最猛性xxxx| 99久久精品费精品国产| 大尺度在线观看| 欧美午夜免费电影| 视频在线观看入口黄最新永久免费国产 | 色悠悠久久久久| a看欧美黄色女同性恋| 欧美精品一区二区三区免费播放| 亚洲色大成网站www久久九九| 好男人在线视频www| 国产精品爽黄69天堂a| 亚洲国产精品第一区二区| 在线观看亚洲大片短视频| 精品国产一区二区三区四区四| 51一区二区三区| 日韩精品在线中文字幕| 国产精品久久久久影视| 懂色av一区二区三区四区| 国产精品香蕉国产| 夜夜嗨av一区二区三区网站四季av| 影音先锋男人在线| 亚洲国产精品va在看黑人| 91片黄在线观看喷潮| 亚洲一卡二卡三卡四卡五卡| 午夜18视频在线观看| 亚洲a在线观看|