Linux基礎開發工具(gcc/g++,yum,vim,make/makefile)

目錄

軟件包管理器——yum

Linux下,軟件的安裝

yum與軟件包的關系

yum命令的運用

1.查看軟件包

2.安裝/刪除軟件包

編輯器——vim

vim的基本概念

vim的基本操作

命令模式命令

移動光標

刪除文字

撤銷上一次操作

跳至指定的行

底行模式命令

編譯器——gcc/g++

預處理

編譯

匯編

鏈接

動態鏈接與靜態鏈接

總結

自動化構建——make/makefile

基本概念

實例

細節

語法擴展

Linux第?個系統程序——進度條

預備知識

練手——倒計時小程序

進度條簡約版

進度條進階版

調試器 - gdb/cgdb

預備知識點

常見命令

watch

條件斷點

新建條件斷點

在新增斷點上設置條件


軟件包管理器——yum

CentOS版本用yum,Ubuntu版本用apt。

Linux下,軟件的安裝

安裝方法有三:

1.源碼安裝。下載程序的源代碼,并進行編譯,得到可執行程序。

2.rpm安裝方式。使用 rpm 命令來安裝 .rpm 格式的軟件包。(不會自動解決依賴關系)

3.yum工具級別安裝。(自動解決依賴關系)

注:這里的依賴關系是指一個軟件可能需要依賴多個庫才能實現。

yum與軟件包的關系

yum命令的運用

1.查看軟件包

[slm@localhost d1]$ yum list | grep lrzsz
lrzsz.x86_64                             0.12.20-36.el7                @anaconda

注:

1,x86_64后綴表示64位系統的安裝包、

2.el7表示的是操作系統發行版的版本。el7表示的是centos7

3.base表示的是“軟件源的名稱。

2.安裝/刪除軟件包

sudo yum install -y 要安裝的軟件
sudo yum remove -y 要卸載的軟件

;安裝要以超級用戶的身份進行,拷貝下來的軟件會在指定的系統目錄中。

編輯器——vim

vim的基本概念

vim有很多中模式但我們掌握三種即可。三種模式分別是:命令模式,插入模式,底行模式。

用一張圖來清晰解決三種模式的切換命令:

三種模式的特點:

命令模式:用命令對文件內容進行刪除或者控制光標的移動等。

插入模式:可以用鍵盤的輸入對文件內容進行修改。

底行模式:文件保存或退出,也可以進行文件替換,找字符串,列出行號等操作。

vim的基本操作

先進入文件 tmp.c

[slm@localhost d1]$vim tmp.c

命令模式命令

移動光標

按「G」:移動到文章的最后
按「 $ 」:移動到光標所在行的“行尾”
按「^」:移動到光標所在行的“行首”
按「w」:光標跳到下個字的開頭
按「e」:光標跳到下個字的字尾
按「b」:光標回到上個字的開頭
按「#l」:光標移到該行的第#個位置,如:5l,56l
按[gg]:進入到文本開始
按[shift+g]:進入文本末端
按「ctrl」+「b」:屏幕往“后”移動?頁
按「ctrl」+「f」:屏幕往“前”移動?頁
按「ctrl」+「u」:屏幕往“后”移動半頁
按「ctrl」+「d」:屏幕往“前”移動半頁

刪除文字

「yw」:將光標所在之處到字尾的字符復制到緩沖區中。
「#yw」:復制#個字到緩沖區
「yy」:復制光標所在行到緩沖區。
「#yy」:例如,「6yy」表示拷貝從光標所在的該行“往下數”6行?字。
「p」:將緩沖區內的字符貼到光標所在位置。注意:所有與“y”有關的復制命令都必須
與“p”配合才能完成復制與粘貼功能。

撤銷上一次操作


「u」:如果您誤執行?個命令,可以馬上按下「u」,回到上?個操作。按多次“u”可以執行
多次回復。
「ctrl + r」: 撤銷的恢復

跳至指定的行


「ctrl」+「g」列出光標所在行的行號。
「#G」:例如,「15G」,表示移動光標至文章的第15行行首。

底行模式命令

列出行號
? 「set nu」: 輸?「set nu」后,會在?件中的每?行前?列出行號。
? 跳到?件中的某?行
? 「#」:「#」號表示?個數字,在冒號后輸??個數字,再按回?鍵就會跳到該行了,如輸?數字
15,再回?,就會跳到?章的第15行。
查找字符
? 「/關鍵字」: 先按「/」鍵,再輸?您想尋找的字符,如果第?次找的關鍵字不是您想要的,可以
?直按「n」會往后尋找到您要的關鍵字為?。
? 「?關鍵字」:先按「?」鍵,再輸?您想尋找的字符,如果第?次找的關鍵字不是您想要的,可
以?直按「n」會往前尋找到您要的關鍵字為?。
保存?件
? 「w」: 在冒號輸?字?「w」就可以將?件保存起來
離開vim
? 「q」:按「q」就是退出,如果?法離開vim,可以在「q」后跟?個「!」強制離開vim。
? 「wq」:?般建議離開時,搭配「w」?起使?,這樣在退出的時候還可以保存文件。

???「q!」:不存盤強制退出vim

其他指令:

!man+函數:查詢函數

!command:不離開vim,進入到命令行輸入頁

vs+文件名:一個窗口產生多個文件,如果文件不存在就新建

ctrl+ww:兩個窗口之間關標切換

在命令行模式下批量化注釋:

1.ctrl+v:進入可視化模式

2.按hjkl鍵選擇要注釋的行

3.shift+i=I//進入插入模式

4.按//

5.按兩下Esc鍵

去注釋:

1.ctrl+v:進入可視化模式

2.按hjkl鍵選擇要刪除的部分

3.按d鍵刪除

編譯器——gcc/g++

預處理

作用:進行宏替換/去注釋/條件編譯/頭文件展開等

gcc -E hello.c -o hello.i

//選項”-E“作用是讓gcc在預處理結束后停止編譯過程

//選項”-o“是指目標文件,".i"文件是預處理的C原始程序

1、頭文件展開就是直接把頭文件中相關的內容拷貝到源文件中,所以預處理后就不需要頭文件

2、條件編譯(#if——#else——#endif),本質是對代碼進行裁剪。比如我們下載軟件的時候有時候會遇到社區版/專業版,在社區版中我們沒有專業版軟件的一些功能,兩個版本的代碼是差不多的,只是兩個版本都新增了一些不同的代碼讓這兩個版本之間產生差別。

3.gcc可以對代碼進行增、刪、改

編譯

作用:檢查代碼的規范性。是否有語法錯誤等,檢查無誤后生成匯編語言。

gcc -S code.i -o code.s

//選項”S“的作用是讓gcc在編譯結束后停止匯編的過程

匯編

作用:生成機器可識別代碼

gcc -c?code.s?-o code.o

//選項”c“的作用是讓gcc在匯編結束后停止鏈接的過程

//不能直接執行,因為.o文件還沒有定位到庫文件中函數的地址,即還沒有把正確的地址補在”地址還不確定的“機器碼上。

鏈接

作用:生成可執行文件或庫文件

gcc hello.o –o hello

//從.c文件直接形成可執行文件

gcc hello.c -o hello //形成hello可執行文件

gcc -o hello hello.c //形成hello可執行文件

gcc hello.c //形成a.out可執行文件

//牢記小秘訣:-o后面都是執行文件

在上面的鏈接的過程中我們發現想要鏈接成功系統里就必須安裝好庫和頭文件,不然找不到函數的地址,所以為什么要有庫呢?

庫的分類

常見的庫有兩種:動態庫和靜態庫

動態庫:在Linux下,后綴為”.so“;在windows下,后綴為”.dll“

靜態庫:在Linux下,后綴為”.a“;在windows下,后綴為”.lib”

庫的命名

在Linux下,靜態庫:"libXXX.a",其中XXX是靜態庫的名字;動態庫:“libXXX.so”,其中XXX是動態庫的名字。

?兩種庫的區別

靜態庫:會在磁盤進行鏈接時把庫文件的代碼全部加入到可執行文件中(實際上就是拷貝),所以生成的文件比較大,但是運行時不需要庫文件了

動態庫:在編譯鏈接時并沒有把庫文件的代碼加入到可執行文件中,而是在運行可執行文件時鏈接需要的庫文件加載到可執行文件中,這樣可以節省系統的開銷。

兩種庫的優缺點

動態庫靜態庫
優點節省資源不依賴任何庫,可以獨立運行
缺點一旦丟失,所有程序無法直接運行體積大,占據資源多,加載速度受影響

靜態庫和動態庫的生成

gcc test.c -o test//形成動態鏈接

gcc test.c -o test_static? ?-static//形成靜態鏈接,比動態鏈接占用的空間大

ldd命令是查詢文件依賴的庫文件。

注:gcc默認生成的二進制程序,是動態鏈接的,可以用file命令檢驗。

動態鏈接與靜態鏈接

動態鏈接就是把程序按照模塊拆分成各個相對獨立部分,在程序運?時才將它們鏈接在?起形成?個完整的程序。每個程序里面的庫函數都是共用一個庫的。

靜態鏈接就是把代碼需要的函數直接拷貝到可執行文件中,每個程序里面的庫函數都要拷貝一份庫函數代碼,會產生很多副本。

總結

1.預處理(去注釋/展開頭文件/進行宏替換/條件編譯等)

2.編譯(檢查代碼規范性,檢查語法錯誤,無誤后生成匯編語言)

3.匯編(生成機器可識別二進制代碼)

4.鏈接(生成可執行文件)

5.形成不同階段文件的簡易記法:Esc鍵變成ESc

有時候我們老是代碼寫完了,但是運行的時候會報錯,但是修改完代碼后,又要開始重新形成目標文件,萬一我們的錯誤改了又錯呢,錯很多遍的話這樣就會很麻煩。如果有個文件一直保存這條命令的話那我每次運行的時候就不需要自己又輸一遍了。

自動化構建——make/makefile

基本概念

作用:一旦寫好makefile,只需要一個make命令就可以讓整個工程完全自動編譯,極大提高了軟件開發的效率。

make是解釋makefile文件中指令的命令,所以make是一條命令,makefile是一個文件。

實例

test_9_10:test_9_10.cgcc -o test_9_10 test_9_10.c
.PHONY:clean
clean:rm -f test_9_10

規范:

細節

[root@localhost d1]# ll
總用量 904
drwxr-xr-x. 3 root root     16 3月  13 15:32 d2
-rw-r--r--. 1 root root     89 9月  10 15:30 makefile
-rwxr-xr-x. 1 root root   8664 9月  10 11:13 test
-rw-r--r--. 1 root root    204 9月  10 15:27 test_9_10.c
-rw-r--r--. 1 root root    553 9月  10 14:19 test.c
-rwxr-xr-x. 1 root root 900440 9月  10 11:13 test_static
[root@localhost d1]# make
gcc -o test_9_10 test_9_10.c
[root@localhost d1]# ll
總用量 916
drwxr-xr-x. 3 root root     16 3月  13 15:32 d2
-rw-r--r--. 1 root root     89 9月  10 15:30 makefile
-rwxr-xr-x. 1 root root   8664 9月  10 11:13 test
-rwxr-xr-x. 1 root root   8416 9月  10 15:31 test_9_10
-rw-r--r--. 1 root root    204 9月  10 15:27 test_9_10.c
-rw-r--r--. 1 root root    553 9月  10 14:19 test.c
-rwxr-xr-x. 1 root root 900440 9月  10 11:13 test_static
[root@localhost d1]# make
make: “test_9_10”是最新的。
[root@localhost d1]# make clean
rm -f test_9_10
[root@localhost d1]# make clean
rm -f test_9_10
[root@localhost d1]# make clean
rm -f test_9_10

在上面的代碼中我們發現

問題1:make命令后只有一條執行指令,clean怎么不執行?

問題2:make命令執行后后面在執行就會顯示文件是最新的,不會執行,但是clean卻能一直執行

問題一:make、makefile默認只形成一個目標,就是從上到下遇到的第一個目標。但是如果第一條指令中依賴文件列表在該目錄下沒有,那么make就會往下面找,就會執行多條指令。

//makefile文件
test_9_10:test_9_10.ogcc -o test_9_10 test_9_10.o
test_9_10.o:test_9_10.sgcc -c test_9_10.s -o test_9_10.o
test_9_10.s:test_9_10.igcc -S test_9_10.i -o test_9_10.s
test_9_10.i:test_9_10.cgcc -E test_9_10.c -o test_9_10.i
.PHONY:clean
clean:rm -f test_9_10 *.i *.s *.o
[root@localhost d1]# ll
總用量 904
drwxr-xr-x. 3 root root     16 3月  13 15:32 d2
-rw-r--r--. 1 root root    278 9月  10 16:03 makefile
-rwxr-xr-x. 1 root root   8664 9月  10 11:13 test
-rw-r--r--. 1 root root    204 9月  10 15:27 test_9_10.c
-rw-r--r--. 1 root root    553 9月  10 14:19 test.c
-rwxr-xr-x. 1 root root 900440 9月  10 11:13 test_static
[root@localhost d1]# make
gcc -E test_9_10.c -o test_9_10.i
gcc -S test_9_10.i -o test_9_10.s
gcc -c test_9_10.s -o test_9_10.o
gcc -o test_9_10 test_9_10.o
[root@localhost d1]# ll
總用量 944
drwxr-xr-x. 3 root root     16 3月  13 15:32 d2
-rw-r--r--. 1 root root    278 9月  10 16:03 makefile
-rwxr-xr-x. 1 root root   8664 9月  10 11:13 test
-rwxr-xr-x. 1 root root   8416 9月  10 16:03 test_9_10
-rw-r--r--. 1 root root    204 9月  10 15:27 test_9_10.c
-rw-r--r--. 1 root root  16921 9月  10 16:03 test_9_10.i
-rw-r--r--. 1 root root   1616 9月  10 16:03 test_9_10.o
-rw-r--r--. 1 root root    576 9月  10 16:03 test_9_10.s
-rw-r--r--. 1 root root    553 9月  10 14:19 test.c
-rwxr-xr-x. 1 root root 900440 9月  10 11:13 test_static

問題2:首先我們先了解“.PHONY”表示被修飾的目標是一個偽目標,偽目標總是要執行的。總是要執行就表示它不需要對比源文件和exe的修改時間,只要make它的指令就會可以一直執行。

 [root@localhost d1]#stat test_9_10.c文件:"test_9_10.c"大小:204       	塊:8          IO 塊:4096   普通文件
設備:fd00h/64768d	Inode:33600218    硬鏈接:1
權限:(0644/-rw-r--r--)  Uid:(    0/    root)   Gid:(    0/    root)
環境:unconfined_u:object_r:home_root_t:s0
最近訪問:2025-09-10 15:31:25.887293504 +0800
最近更改:2025-09-10 15:27:21.934213096 +0800
最近改動:2025-09-10 15:27:21.936213031 +0800
創建時間:-
[root@localhost d1]# vim test_9_10.c
[root@localhost d1]# stat test_9_10.c文件:"test_9_10.c"大小:216       	塊:8          IO 塊:4096   普通文件
設備:fd00h/64768d	Inode:33600234    硬鏈接:1
權限:(0644/-rw-r--r--)  Uid:(    0/    root)   Gid:(    0/    root)
環境:unconfined_u:object_r:home_root_t:s0
最近訪問:2025-09-10 19:39:14.639976185 +0800
最近更改:2025-09-10 19:39:14.639976185 +0800
最近改動:2025-09-10 19:39:14.642975744 +0800
創建時間:-
//?件 = 內容 + 屬性
//Modify: 內容變更,時間更新(最近改動)
//Change:屬性變更,時間更新(最近更改)
//Access:常指的是?件最近?次被訪問的時間。在Linux的早期版本中,每當?件被訪問時,其
//atime都會更新。但這種機制會導致?量的IO操作。具體更新原則,不做過多解釋。

make執行第一條不是偽目標的指令時,會先比較文件的源文件是否在可執行文件的前后時間,來決定是否要重新編譯。如果源文件的修改時間比可執行文件晚,那么就不需要重新編譯,否則,需要。

語法擴展

BIN=proc.exe定義變量(類似于宏替換)
SRC=$(shell ls *.c)?采?shell命令??式,獲取當前所有.c?件名
SRC=$(wildcard *.c)使? wildcard 函數,獲取當前所有.c?件名
OBJ=$(SRC:.c=.o)將SRC的所有同名.c 替換 成為.o 形成?標?件列表
LFLAGS=-o鏈接選項
FLAGS=-c編譯選項
RM=rm -f引?命令
$(BIN):$(OBJ)
@$(CC) $(LFLAGS) $@ $^
$@:代表?標?件名。 $^: 代表依賴?件列表
@$(CC) $(FLAGS) $<%<: 對展開的依賴.c?件,?個?個的交給gcc。
@echo "compling ... $< to $@"?@:不回顯命令,如果不加 @,終端會顯示:

echo "compling ... xxx.c to xxx.o"

然后再顯示:

compling ... xxx.c to xxx.o

加了 @,終端只會顯示:

compling ... xxx.c to xxx.o

clean:
$(RM) $(OBJ) $(BIN)
#
$(RM): 替換,?變量內容替換它
%.o:%.c%.c 展開當前?錄下所有的.c。 %.o: 同時展開同
名.o

實例:

  1 BIN=test_9_102 SRC=$(wildcard *.c)3 OBJ=$(SRC:.c=.o)4 LFLAGS=-o5 FLAGS=-c6 CC=gcc7 RM= rm -f8 $(BIN):$(OBJ)9     @$(CC) $(LFLAGS) $@ $^10 %.o:%.c11     @$(CC) $(FLAGS) $<     12     @echo "compling ...$< to $@"13 .PHONY:clean14 clean:15       $(RM) $(OBJ) $(BIN)  //相當于rm -f *.o test_9_10

執行make指令:

[root@localhost d1]# make
compling ...test_9_10.c to test_9_10.o
[root@localhost d1]# ll
總用量 904
drwxr-xr-x. 3 root root     16 3月  13 15:32 d2
-rw-r--r--. 1 root root    228 9月  10 20:42 makefile
-rwxr-xr-x. 1 root root   8416 9月  10 20:35 test_9_10
-rw-r--r--. 1 root root    204 9月  10 20:35 test_9_10.c
-rw-r--r--. 1 root root   1616 9月  10 20:35 test_9_10.o
-rwxr-xr-x. 1 root root 900440 9月  10 11:13 test_static
[root@localhost d1]# make clean
rm -f test_9_10.o test_9_10
[root@localhost d1]# ll
總用量 888
drwxr-xr-x. 3 root root     16 3月  13 15:32 d2
-rw-r--r--. 1 root root    228 9月  10 20:42 makefile
-rw-r--r--. 1 root root    204 9月  10 20:35 test_9_10.c
-rwxr-xr-x. 1 root root 900440 9月  10 11:13 test_static

Linux第?個系統程序——進度條

預備知識

回車(\r)/換行(\n):

\r:把光標移到行首(不換行)

\n:把光標移到下一行

行緩沖區:

函數:fflush

#include<stdio.h>? ?int fflush(FILE*stream)//把用戶緩沖區的內容刷新到內核緩沖區中,并寫在文件stream中

比較下面三種結果有何不同:

  1 #include<stdio.h>2 int main()3 {4     printf("hello world\n");5     sleep(3);6     return 0;7 }

現象:立馬打印“hello world”,然后光標在下一行閃爍三秒,然后打印命令條

  1 #include<stdio.h>2 int main()3 {4     printf("hello world");5     sleep(3);6     return 0;7 }

現象:等待三秒后才打印“hello world”,然后在同一行上打印命令條

  1 #include<stdio.h>2 int main()3 {4     printf("hello world");5     fflush(stdout);6     sleep(3);7     return 0;8 }

現象:立馬打印“hello world”,等待三秒后,然后在同一行上打印命令條

所以從上面的現象可以得出,

1.回車鍵和fflush函數可以進行行緩沖,把用戶緩沖區的內容刷新到內核緩沖區并刷新到輸出設備上。

2.程序結束也會自動刷新緩沖區。

練手——倒計時小程序

  1 #include<stdio.h>2 int main()3 {4     int i=20;5     while(i--)6     {7         printf("%-2d\r",i);//保留兩位數字8         fflush(stdout);9         sleep(1);10 11     }12     printf("\n");13     return 0;14 }

進度條簡約版

  //每秒加載1%1 #include<stdio.h>2 #include<string.h>3 int main()4 {5     char str[101]={0};6     int i=0;7     for(i=0;i<=100;i++)8     {9         printf("[%-100s]    %d%%\r",str,i);10         str[i]='#';11         fflush(stdout);12         sleep(1);13 14     }15     printf("\n");16 17     return 0;18 }

我們常見的進度條都是會根據我們的網速來確定加載了多少,所以我們來實現一個進階版

進度條進階版

[root@localhost d1]# ./process
[####################################################################################################] ?[-] ?[100%]
download 1025.00MB Done
?

main.c

  1 #include"process.h"2 double speed=1.0;3 double size=1024.0;4 void download()5 {6 7     double current=0;8     while(current<=size)9     {10         //打印進度條11         PrintfProcess(current,size);12         current+=speed;//注釋掉,可以觀察到進度一直在加載13         usleep(20000);14     }15     printf("\ndownload %.2lfMB Done\n",current);//current類型寫錯,輸出0.0016 }17 int main()18 {19     download();20     return 0;21 }

process.c

  1 #include"process.h"2 void PrintfProcess(double current,double size)3 {4     char str[101];5     memset(str,0,sizeof(str));6     const char*lable="-\\|/";//“\\”轉義字符用來表示進度的加載效率7     int len=strlen(lable);8     int i=0;9     int num=(int)(current/size*100);10     for(i=0;i<num;i++)11     {12         str[i]='#';13     }14     static int cnt;15     cnt%=len;16     printf("[%-100s]  [%c]  [%.lf%%]\r",str,lable[cnt],current/size*100);17     cnt++;//即使卡頓了也一直在加載,檢測網絡在不在線18     fflush(stdout);19 }

lable字符串的作用:

process.h

  1 #pragma once2 #include<stdio.h>3 #include<unistd.h>4 #include<string.h>5 void PrintfProcess(double current,double size);

makefile

  1 SRC=$(wildcard *.c)2 OBJ=$(SRC:.c=.o)3 BIN=process4 $(BIN):$(OBJ)5     gcc -o $@ $^6 %.o:%.c7     gcc -c $<8 .PHONY:clean9 clean:10     rm -f $(OBJ) $(BIN)

調試器 - gdb/cgdb

樣例代碼:

// mycmd.c
#include <stdio.h>
int Sum(int s, int e)
{int result = 0;for(int i = s; i <= e; i++){result += i;}return result;
}
int main()
{int start = 1;int end = 100;printf("I will begin\n");int n = Sum(start, end);printf("running done, result is: [%d-%d]=%d\n", start, end, n);return 0;
}

預備知識點

1.程序有兩種發布方式,debug模式和release模式。Linux gcc/g++出來的二進制程序,默認時release模式。

2.debug模式才允許被調試,所以要使用gdb調試,必須在源代碼生成二進制程序的時候,加上-g選項,如果沒有添加,就不能進行調試。

[root@localhost d1]# gcc -o mycmd mycmd.c//默認模式,不支持調試
[root@localhost d1]# gdb mycmd
(gdb) l 1
No symbol table is loaded. ?Use the "file" command.
(gdb) quit
[root@localhost d1]# gcc -o mycmd mycmd.c -g//debug模式,支持調試
[root@localhost d1]# gdb mycmd
(gdb) l 1
5 ? ? ? int i;

常見命令

進入調試:gdb+可執行文件

退出調試:ctrl+d或q

命令作?樣例
list/l顯示源代碼,從源文件中光標那行開始list/l 10
list/l 函數名列出指定函數的源代碼list/l mian
list/l 文件名:行號列出指定文件的源代碼,如果只要指定的哪一行,那么就先設置 set listsize 1,就可以指定看哪一行,否則都是從第一行開始展示list/l mycmd.c:1
r/run從程序開始連續執行run
n/next單步執行,不進入函數內部,相當于逐過程F10next
s/step單步執行,進入函數內部,相當于逐語句F11
break/b?在指定行號設置斷點

b 10

break mycmd.c 10

break/b 函數名在函數開頭設置斷點break main
info break/b查看所有斷點信息info break
finish執行到當前函數的返回,然后停止
print/p 表達式打印表達式的值print end+start
?p 變量打印指定變量的值p x
set var 變量=值修改變量的值set var i=10
continue/c從當前位置開始連續執行程序continue
delete/d breakpoints刪除所有斷點
delete/d breakpoints n刪除序號為n的斷點delete/d breakpoints 1
disable breakpoints禁用所有斷點
enable breakpoints啟用所有斷點
display 變量名跟蹤顯示指定變量的值(每次停止時)display x
undisplay 編號取消對指定編號的變量的跟蹤顯示undisplay 1
until x行號執行到指定行號until 10
backtrace/bt查看當前執行棧的各級函數調用及參數
info/i locals查看當前棧幀的局部變量值
quit/q退出gdb調試器

注:n、s、finish、c、display/undisplay、until都必須在執行期間才可以使用。

watch

執行時監視?個表達式(如變量)的值。如果監視的表達式在程序運行期間的值發生變化,GDB 會暫停程序的執行,并通知使用者。

(gdb) l main
8				 result += i;
9		  }
10		 return result;
11	}
12	int main()
13	{
14		 int start = 1;
15		 int end = 100;
16		 printf("I will begin\n");
17		int n = Sum(start, end);
(gdb) b 17
Breakpoint 1 at 0x4005cd: file mycmd.c, line 17.
(gdb) r
Starting program: /home/d1/mycmd 
I will beginBreakpoint 1, main () at mycmd.c:17
17		int n = Sum(start, end);
Missing separate debuginfos, use: debuginfo-install glibc-2.17-326.el7_9.3.x86_64
(gdb) s
Sum (s=1, e=100) at mycmd.c:4
4		 int result = 0;
(gdb) n
6		 for(i = s; i <= e; i++)
(gdb) watch result
Hardware watchpoint 2: result
(gdb) c
Continuing.
Hardware watchpoint 2: resultOld value = 0
New value = 1
Sum (s=1, e=100) at mycmd.c:6
6		 for(i = s; i <= e; i++)
(gdb) c
Continuing.
Hardware watchpoint 2: resultOld value = 1
New value = 3
Sum (s=1, e=100) at mycmd.c:6
6		 for(i = s; i <= e; i++)

注:如果你有一些變量不應該修改,但是你懷疑它修改導致了問題,你可以watch它,如
果變化了,就會通知。

條件斷點

實際上就是在設置斷點的時候給斷點加個條件,當運行起來后finish就會停在設置條件的那個位置。比如 b 8?if i==30,那么程序就會在第八行且i=30的時候停止執行。可以驗證中間部分是否結果錯誤。

新建條件斷點

(gdb) l Sum
1	#include <stdio.h>
2	int Sum(int s, int e)
3	{
4		 int result = 0;
5		 int i;
6		 for(i = s; i <= e; i++)
7		 {
8				 result += i;
9		  }
10		 return result;
(gdb) l main
8				 result += i;
9		  }
10		 return result;
11	}
12	int main()
13	{
14		 int start = 1;
15		 int end = 100;
16		 printf("I will begin\n");
17		int n = Sum(start, end);
(gdb) b 17
Breakpoint 1 at 0x4005cd: file mycmd.c, line 17.
(gdb) r
Starting program: /home/d1/mycmd 
I will beginBreakpoint 1, main () at mycmd.c:17
17		int n = Sum(start, end);
Missing separate debuginfos, use: debuginfo-install glibc-2.17-326.el7_9.3.x86_64
(gdb) s
Sum (s=1, e=100) at mycmd.c:4
4		 int result = 0;
(gdb) s
6		 for(i = s; i <= e; i++)
(gdb) n
8				 result += i;
(gdb) n
6		 for(i = s; i <= e; i++)
(gdb) n
8				 result += i;
(gdb) b 8 if i==30
Breakpoint 2 at 0x400596: file mycmd.c, line 8.
(gdb) display i
1: i = 2
(gdb) finish
Run till exit from #0  Sum (s=1, e=100) at mycmd.c:8Breakpoint 2, Sum (s=1, e=100) at mycmd.c:8
8				 result += i;
1: i = 30
(gdb) p result//可以查看result的值
$1 = 435

在新增斷點上設置條件

(gdb) b 17
Breakpoint 1 at 0x4005cd: file mycmd.c, line 17.
(gdb) r
Starting program: /home/d1/mycmd?
I will begin

Breakpoint 1, main () at mycmd.c:17
17?? ??? ?int n = Sum(start, end);
Missing separate debuginfos, use: debuginfo-install glibc-2.17-326.el7_9.3.x86_64
(gdb) s
Sum (s=1, e=100) at mycmd.c:4
4?? ??? ? int result = 0;
(gdb) s
6?? ??? ? for(i = s; i <= e; i++)
(gdb) n
8?? ??? ??? ??? ? result += i;
(gdb) n
6?? ??? ? for(i = s; i <= e; i++)
(gdb) n
8?? ??? ??? ??? ? result += i;
(gdb) n
6?? ??? ? for(i = s; i <= e; i++)
(gdb) n
8?? ??? ??? ??? ? result += i;
(gdb) b
Breakpoint 2 at 0x400596: file mycmd.c, line 8.
(gdb) info b
Num ? ? Type ? ? ? ? ? Disp Enb Address ? ? ? ? ? ?What
1 ? ? ? breakpoint ? ? keep y ? 0x00000000004005cd in main at mycmd.c:17
?? ?breakpoint already hit 1 time
2 ? ? ? breakpoint ? ? keep y ? 0x0000000000400596 in Sum at mycmd.c:8
(gdb) condition 2 i==30 //不需要if
(gdb) info b
Num ? ? Type ? ? ? ? ? Disp Enb Address ? ? ? ? ? ?What
1 ? ? ? breakpoint ? ? keep y ? 0x00000000004005cd in main at mycmd.c:17
?? ?breakpoint already hit 1 time
2 ? ? ? breakpoint ? ? keep y ? 0x0000000000400596 in Sum at mycmd.c:8
?? ?stop only if i==30
?? ?breakpoint already hit 2 times
(gdb) n
6?? ??? ? for(i = s; i <= e; i++)
(gdb) n
8?? ??? ??? ??? ? result += i;
(gdb) c
Continuing.

Breakpoint 2, Sum (s=1, e=100) at mycmd.c:8
8?? ??? ??? ??? ? result += i;
(gdb) p i
$2 = 30
(gdb) p result
$3 = 435

注:Ctrl+X松開后按a就可以進入GDB TUI(Text User Interface)模式 下的分屏操作,按Esc可以切換到源代碼區域,可以按上下鍵實現翻頁;按i鍵可以切換回gdb模式。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/98080.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/98080.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/98080.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

數據結構之跳表

跳表&#xff08;Skip List&#xff09;是一種基于概率平衡的數據結構&#xff0c;通過多層有序鏈表實現高效的查找、插入和刪除操作。它在最壞情況下時間復雜度為 (O(n))&#xff0c;但通過隨機化設計&#xff0c;平均時間復雜度可優化至 (O(\log n))&#xff0c;與平衡二叉搜…

線程概念,控制

一、線程概念 線程概念&#xff1a;進程內部的一個執行流&#xff0c;輕量化。 觀點&#xff1a;進程是系統分配資源的基本單位&#xff0c;線程是CPU調度的基本單位。 在理解線程之前&#xff0c;我們在談一下虛擬地址空間。 我們都知道進程是通過頁表將虛擬地址轉化為物理地址…

RabbitMQ 高可用實戰篇(Mirrored Queue + Cluster + 持久化整合)

RabbitMQ 高可用實戰篇&#xff08;Mirrored Queue Cluster 持久化整合&#xff09;1. 前言 在生產環境中&#xff0c;單節點 RabbitMQ 容易因故障導致消息丟失或業務中斷。 通過高可用隊列、集群部署和持久化策略&#xff0c;可以保證 消息可靠性、節點容錯和持續服務。 本文…

支持向量機:從理論到實踐

支持向量機&#xff1a;從理論到實踐 文章目錄支持向量機&#xff1a;從理論到實踐一。理論概述1. 線性可分支持向量機1.1 基本概念與數學形式1.2 函數間隔與幾何間隔1.3 間隔最大化與優化問題1.4 拉格朗日對偶理論與求解1.5 支持向量與決策函數2. 近似線性可分數據&#xff08…

LVS與Keepalived詳解(二)LVS負載均衡實現實操

文章目錄前言一、LVS-DR 模式詳解1.1 數據包流向分析1.2 DR 模式的特點二、LVS-DR 集群部署實戰2.1 環境準備2.2 配置負載調度器&#xff08;Director Server&#xff09;2.3 配置節點服務器&#xff08;Real Server&#xff09;2.4 測試驗證三、前期回顧3.1 LVS 三種工作模式及…

歸一化實現原理

歸一化&#xff08;Normalization&#xff09;是一種將數據轉換到相同尺度的預處理技術&#xff0c;它通常用于讓不同特征&#xff08;或數據項&#xff09;具有相同的量綱或范圍。在聯邦學習中&#xff0c;歸一化可以用來處理非獨立同分布&#xff08;Non-IID&#xff09;**數…

企業級實戰:構建基于Qt、C++與YOLOv8的模塊化工業視覺檢測系統

一、概述 在追求高效與精密的現代制造業中&#xff0c;自動化光學檢測&#xff08;AOI&#xff09;已成為保障產品質量的核心技術。傳統的質檢流程往往受限于人工效率與主觀判斷&#xff0c;難以滿足大規模、高精度的生產需求。本文旨在研發一套完整的、企業級的工業視覺異常檢…

【目標檢測】metrice_curve和loss_curve對比圖可視化

代碼如下&#xff1a; import warnings warnings.filterwarnings(ignore)import os import pandas as pd import numpy as np import matplotlib.pylab as pltpwd os.getcwd()names [model1, model2, model3,ours]plt.figure(figsize(10, 10))plt.subplot(2, 2, 1) for i in …

【LeetCode hot100|Week2】滑動窗口,子串

筆記用于個人復習和鞏固&#xff0c;題解非原創&#xff0c;參考LeetCode官方題解以及各個大佬的解法&#xff0c;希望給大家帶來幫助&#xff0c;同時筆記也能督促我學習進步 這周主要把滑動窗口和子串的題目刷了一遍 文章目錄Week2D1 滑動窗口209. 長度最小的子數組713. 乘積…

vue2純前端對接海康威視攝像頭實現實時視頻預覽

vue2純前端對接海康威視攝像頭實現實時視頻預覽一、環境準備二、代碼集成1.1 準備webrtcstreamer.js&#xff0c;粘貼即用&#xff0c;不用做任何修改1.2 封裝視頻組件&#xff0c;在需要視頻的地方引入此封裝的視頻組件即可&#xff0c;也是粘貼即用&#xff0c;注意其中impor…

Android 設置禁止截圖和禁止長截圖

1.禁止截圖 在 Activity 代碼中 , 可以在調用 setContentView 函數之前 ,為 Window 窗口對象 設置 LayoutParams.FLAG_SECURE 標志位 , 可以禁止對本界面進行截屏 ,Window 窗口對象 , 可通過 getWindow 方法獲取 ,核心代碼如下 :getWindow().setFlags(LayoutParams.FLAG_SECUR…

AR 巡檢在工業的應用|阿法龍XR云平臺

AR 巡檢的應用覆蓋電力、石油化工、智能制造、軌道交通、冶金等對設備可靠性和安全性要求極高的行業&#xff0c;具體場景包括&#xff1a;電力行業變電站內設備的狀態檢查&#xff1a;通過 AR 眼鏡掃描設備&#xff0c;實時顯示設備額定參數、歷史故障記錄、實時傳感器數據&am…

【C++】STL詳解(七)—stack和queue的介紹及使用

? 堅持用 清晰易懂的圖解 代碼語言&#xff0c; 讓每個知識點都 簡單直觀 &#xff01; &#x1f680; 個人主頁 &#xff1a;不呆頭 CSDN &#x1f331; 代碼倉庫 &#xff1a;不呆頭 Gitee &#x1f4cc; 專欄系列 &#xff1a; &#x1f4d6; 《C語言》&#x1f9e9; 《…

深度學習周報(9.8~9.14)

目錄 摘要 Abstract 1 LSTM相關網絡總結與對比 1.1 理論總結 1.2 代碼運行對比 2 量子計算入門 3 總結 摘要 本周首先總結了LSTM、Bi-LSTM與GRU的區別與優缺點&#xff0c;對比了三者實戰的代碼與效果&#xff0c;還另外拓展了一些循環神經網絡變體&#xff08;包括窺視…

Quat 四元數庫使用教程:應用場景概述

基礎概念 四元數是一個包含四個元素的數組 [x, y, z, w]&#xff0c;其中 x,y,z表示虛部&#xff0c;w 表示實部。單位四元數常用于表示3D空間中的旋轉。 1. 創建和初始化函數 create() - 創建單位四元數 應用場景&#xff1a;初始化一個新的四元數對象&#xff0c;通常作為其他…

【Java后端】Spring Boot 多模塊項目實戰:從零搭建父工程與子模塊

如何用 Spring Boot 搭建一個父工程 (Parent Project)&#xff0c;并在其中包含多個子模塊 (Module)&#xff0c;適合企業級項目或者需要分模塊管理的場景。Spring Boot 多模塊項目實戰&#xff1a;從零搭建父工程與子模塊在日常開發中&#xff0c;我們經常會遇到這樣的需求&am…

企業級AI會議系統技術實現:快鷺如何用AI重構會議全流程

摘要 本文深度解析快鷺AI會議系統的核心技術架構&#xff0c;重點探討其在語音識別、自然語言處理、數據集成和安全防護等方面的技術實現。通過對比傳統會議系統的技術痛點&#xff0c;分析快鷺AI如何通過技術創新實現會議籌備時間減少67%、數據調取速度提升100倍的顯著效果。…

【CSS學習筆記3】css特性

1css三大特性 1.1層疊性&#xff1a;就近原則&#xff0c;最新定義的樣式 1.2繼承性&#xff1a;子標簽集成父標簽的樣式&#xff0c;如文本和字號 行高的繼承&#xff1a;不加單位指的是當前文字大小的倍數 body {font: 12px/1.5 Microsoft YaHei;color: #be1313;} div {…

[C語言]常見排序算法①

1.排序的概念及常見的排序算法排序在咱們日常生活中十分的常見&#xff0c;就好比是網上購物的時候通常能夠選擇按照什么排序&#xff0c;比如價格、評論數量、銷量等。那么接下來咱們就來了解一些關于排序的概念。排序&#xff1a;所謂排序&#xff0c;就是使一串記錄&#xf…

文獻閱讀筆記:RS電子戰測試與測量技術文檔

信息來源&#xff1a;羅德與施瓦茨&#xff08;Rohde & Schwarz&#xff09;公司關于電子戰&#xff08;Electronic Warfare, EW&#xff09;測試與測量解決方案專業技術文檔。 該文檔由臺灣地區應用工程師Mike Wu撰寫&#xff0c;核心圍繞電子戰基礎、雷達系統、實戰應用及…