首先就是要熟練在vim里面寫代碼,其實(shí)就是沒有提示和自動(dòng)補(bǔ)全了,這個(gè)問題并不大。
我服務(wù)器gcc版本是4.8.5,所以就按照這個(gè)來了 https://gcc.gnu.org/onlinedocs/gcc-4.8.5/gcc/
其實(shí)我的開發(fā)者環(huán)境是最新的9.1.0,非常不建議哦。生產(chǎn)環(huán)境和開發(fā)環(huán)境盡量相同,不同的話一定要進(jìn)行大量的測(cè)試
然后就是編譯,先cd到工程文件夾,然后使用編譯命令編譯
一、編譯編譯:當(dāng)前源代碼編譯成二進(jìn)制目標(biāo)文件(.obj文件)
鏈接(link):將生成的.obj文件與庫文件.lib等文件鏈接,生成可執(zhí)行文件
一個(gè)現(xiàn)代編譯器的主要工作流程如下:
源程序(source code)→預(yù)處理器(preprocessor)→編譯器(compiler)→匯編程序(assembler)→目標(biāo)程序(object code)→連接器(鏈接器,Linker)→可執(zhí)行程序(executables)
執(zhí)行過程 雖然我們稱gcc是C語言的編譯器,但使用gcc由C語言源代碼文件生成可執(zhí)行文件的過程不僅僅是編譯的過程,而是要經(jīng)歷四個(gè)相互關(guān)聯(lián)的步驟∶
1.預(yù)處理(也稱預(yù)編譯,Preprocessing):命令gcc首先調(diào)用cpp進(jìn)行預(yù)處理,在預(yù)處理過程中,對(duì)源代碼文件中的文件包含(include)、預(yù)編譯語句(如宏定義define等)進(jìn)行分析。
2.編譯(Compilation):接著調(diào)用cc1進(jìn)行編譯,這個(gè)階段根據(jù)輸入文件生成以.o為后綴的目標(biāo)文件。
3.匯編(Assembly):匯編過程是針對(duì)匯編語言的步驟,調(diào)用as進(jìn)行工作,一般來講,.S為后綴的匯編語言源代碼文件、.s為后綴的匯編語言文件經(jīng)過預(yù)編譯和匯編之后都生成以.o為后綴的目標(biāo)文件。
4.鏈接(Linking):當(dāng)所有的目標(biāo)文件都生成之后,gcc就調(diào)用ld來完成最后的關(guān)鍵性工作,這個(gè)階段就是連接。在連接階段,所有的目標(biāo)文件被安排在可執(zhí)行程序中的恰當(dāng)?shù)奈恢茫瑫r(shí),該程序所調(diào)用到 的庫函數(shù)也從各自所在的檔案庫中連到合適的地方。
實(shí)例:
1.編寫hello.c文件2.預(yù)編譯過程:gcc -E ./hello.c -o hello.i //.i 為后綴的文件,是已經(jīng)預(yù)處理過的C源代碼文件,可以省略這一步。
cat hellp.c | wc -l //查看hello.c文件內(nèi)容的行數(shù)。
cat hellp.i | wc -l //查看hello.i文件內(nèi)容的行數(shù)。
3.匯編過程:gcc -S hello.i -o hello.s //.s為后綴的文件,是匯編語言源代碼文件;可以省略這一步。
4.編譯過程gcc -c ./hello.c //在當(dāng)前文件夾下生成hello.o .o為后綴的文件,是編譯后的目標(biāo)文件;
gcc -c hello.c -o hello.o //在當(dāng)前文件夾下生成hello.o
5.鏈接過程:gcc hello.o -o hello
6.直接在終端輸入文件路徑或者把hello文件拖動(dòng)到終端即可執(zhí)行用g++編譯c++源程序
用g++編譯c++源程序和c語言類似,可將gcc改為g++逐個(gè)嘗試。以下只提供一些簡單介紹:
-E Preprocess only; do not compile, assemble or link
-S Compile only; do not assemble or link
-c Compile and assemble, but do not link
-o Place the output into
-g Use of extra debugging information
-w 關(guān)閉編譯時(shí)的警告
-o 參數(shù)謹(jǐn)慎使用,也許開了編譯優(yōu)化會(huì)出現(xiàn)問題,但是開了編譯優(yōu)化代碼真的會(huì)變快,做好測(cè)試就行
二、gdb調(diào)試assert斷言函數(shù) 如果參數(shù)expression等于零,一個(gè)錯(cuò)誤消息將會(huì)寫入到設(shè)備的標(biāo)準(zhǔn)錯(cuò)誤集并且會(huì)調(diào)用abort函數(shù),就會(huì)結(jié)束程序的執(zhí)行。這個(gè)雖然可以找到錯(cuò)誤,但是我們有更厲害的東西
gdb的其實(shí)是一個(gè)可執(zhí)行文件,所以我們需要先編譯出這個(gè)文件

#include <stdio.h>int main()
{ int a = 0;
printf("%d\n", a++);
printf("%d\n", a--);
printf("%d\n", ++a);
printf("%d\n", --a);
}gcc -g A.c -o A
命令中出現(xiàn)了-g參數(shù),這個(gè)不僅可以創(chuàng)建符號(hào)表,符號(hào)表包含了程序中使用的變量名稱的列表,而且可以關(guān)閉所有的優(yōu)化機(jī)制,以便程序執(zhí)行過程中嚴(yán)格按照原來的C代碼進(jìn)行。
一定要記得加入這個(gè)參數(shù)
輸入gdb就可以有了,當(dāng)然你可能不想看到那一坨,可以加-q參數(shù)得到一個(gè)清爽的界面
gdb后可以file 跟上文件名,也可以進(jìn)入之后再指定
[root@BobHuang ~]# gdb -q A
Reading symbols from /root/A...done.
(gdb) file A
想回過頭看看以前的代碼,就用list,一次可以顯示十行,繼續(xù)list可以顯示接下來的十行
(gdb) list
1 #include<stdio.h>
2 int main()
3 {
4 int a=0;
5 printf("%d\n",a++);
6 printf("%d\n",a--);
7 printf("%d\n",++a);
8 printf("%d\n",--a);
9 }
10
list默認(rèn)參數(shù)可以用show listsize來查看,如果感覺10行太多或者太少,還可以用set listsize <count>來更改。
但是我有時(shí)候只是想部分,就可以給list加上參數(shù)
list 還可以加上其他參數(shù),比如:
list 5,10 顯示第5行到第10行的代碼;
list func 顯示func函數(shù)周圍的代碼,顯示范圍和list參數(shù)有關(guān);
list test.c:5,10 顯示源文件test.c第5行到第10行的代碼,一般用于調(diào)試含多個(gè)源文件的程序。
gdb 還支持字符串查找,search str,從當(dāng)前行開始,向前查找含str的字符串;
reverse-search str,從當(dāng)前行開始,向后查找含str的字符串。
在gdb里也可以使用shell+命令,比如
shell clear
就會(huì)完成清屏
然后就可以設(shè)置斷點(diǎn)了,和在圖形界面類似,可以設(shè)置在某一行斷點(diǎn)。甚至可以直接寫一個(gè)判斷表達(dá)式
(gdb) break 5
Breakpoint 1 at 0x40052c: file A.c, line 5.
(gdb) break 6 if a==1
Breakpoint 2 at 0x400546: file A.c, line 6.
(gdb) break 7 if a==1
Breakpoint 3 at 0x400560: file A.c, line 7.
然后可以通過info breakpoints來查看斷點(diǎn)
(gdb) info breakpoints
Num Type Disp Enb Address What
1 breakpoint keep y 0x000000000040052c in main at A.c:5
2 breakpoint keep y 0x0000000000400546 in main at A.c:6
stop only if a==1
3 breakpoint keep y 0x0000000000400560 in main at A.c:7
stop only if a==1
Num表示斷點(diǎn)的編號(hào);Type表示斷點(diǎn)的斷點(diǎn)的類型,第二個(gè)斷點(diǎn)類型還加上了條件;Disp表示中斷點(diǎn)在執(zhí)行一次之后是否失去作用,dis為是,keep為不是;Enb表示當(dāng)前中斷點(diǎn)是否有效,y為是,n為否;Address表示中斷點(diǎn)所處的內(nèi)存地址;What指出斷點(diǎn)所處的位置。
(gdb) run
Starting program: /root/A
Breakpoint 1, main () at A.c:5
5 printf("%d\n",a++);
Missing separate debuginfos, use: debuginfo-install glibc-2.17-260.el7_6.5.x86_64
(gdb) continue
Continuing.
0
Breakpoint 2, main () at A.c:6
6 printf("%d\n",a--);
(gdb) continue
Continuing.
1
1
0
[Inferior 1 (process 32035) exited with code 02]
但是他提示我軟件沒裝啊,我們裝一下
(gdb) shell debuginfo-install glibc-2.17-260.el7_6.5.x86_64
再次運(yùn)行,沒有變化,也就是沒有經(jīng)過breakpoint3,也就證明了,執(zhí)行斷點(diǎn)3時(shí)a!=1,所以這個(gè)判斷非常好用啊,能檢測(cè)出某些異常,不過bug復(fù)現(xiàn)是不太好實(shí)現(xiàn)
接下來就是刪除斷點(diǎn)了。如果不需要程序在該斷點(diǎn)暫停時(shí),有兩種方法,一種是使該斷點(diǎn)失效,一種是直接刪除該斷點(diǎn)。使斷點(diǎn)失效用的是Num,刪除斷點(diǎn)用的是行,這樣就巧妙完成了需求
(gdb) disable 2
(gdb) info breakpoints
Num Type Disp Enb Address What
2 breakpoint keep n 0x000000000040052c in main at A.c:5
(gdb) clear 5
Deleted breakpoint 1
delete命令后面的參數(shù)也為Num;可以一次刪除多個(gè)斷點(diǎn),斷點(diǎn)編號(hào)之間用空格隔開;如果delete后沒有參數(shù),默認(rèn)刪除所有斷點(diǎn),會(huì)給出提示選擇是否操作。
上面雖然展示了一下,但是我們需要更多的演示,才展示他的強(qiáng)大
run,開始運(yùn)行程序;
continue,程序暫停時(shí)繼續(xù)運(yùn)行程序的命令;
print 變量名或表達(dá)式,打印該變量或者該表達(dá)式的值。whatis 變量名或者表達(dá)式,可以顯示該變量或表達(dá)式的數(shù)據(jù)類型。
print 變量=值,這種形式還可以給對(duì)應(yīng)的變量賦值;類似的還有set variable 變量=值。作用和用print賦值相同。
next,繼續(xù)執(zhí)行下一條語句;
還有一條命令step,與之類似,不同的是,當(dāng)下一條語句遇到函數(shù)調(diào)用的時(shí)候,next不會(huì)跟蹤進(jìn)入函數(shù),而是繼續(xù)執(zhí)行下面的語句,而step命令則會(huì)跟蹤進(jìn)入函數(shù)內(nèi)部。
(gdb) run
Starting program: /root/A
Breakpoint 2, main () at A.c:55 printf("%d\n",a++);
(gdb) next //繼續(xù)執(zhí)行下一條語句,只執(zhí)行一條06 printf("%d\n",a--);
(gdb) continue //讓程序繼續(xù)運(yùn)行,直到下個(gè)斷點(diǎn)或者結(jié)束Continuing.
110[Inferior 1 (process 6553) exited with code 02]直接賦值的結(jié)果
(gdb) run
Starting program: /root/A
Breakpoint 2, main () at A.c:55 printf("%d\n",a++);
(gdb) print a=10$1 = 10(gdb) continue
Continuing.10111110[Inferior 1 (process 6693) exited with code 03]還有nexti和stepi命令,這兩個(gè)是單步執(zhí)行一條機(jī)器指令,比如(i=0;i<n;i++)這條語句需要輸入多個(gè)nexti才能執(zhí)行完;兩個(gè)的區(qū)別和上面相同。
quit,退出gdb調(diào)試,如果調(diào)試中想要退出,可以直接輸入該命令,會(huì)出現(xiàn)提示選擇是否退出。kill命令,結(jié)束當(dāng)前程序的調(diào)試,(不會(huì)退出gdb)。
三、makefile編寫makefile帶來直接好處就是——“自動(dòng)化編譯”。一旦寫好,只需要一個(gè)make命令,整個(gè)工程完全自動(dòng)編譯,所以十分方便。而Makefile文件就是告訴make命令怎么樣地去編譯和鏈接程序。但是想要比較靈活的運(yùn)用它,還是先要熟悉一些關(guān)于系統(tǒng)對(duì)程序編譯和鏈接的知識(shí)。


相關(guān)推薦
最高頻率為1MHz的雙相時(shí)鐘振蕩器
男女關(guān)系的33個(gè)絕妙比喻
2010全球電子峰會(huì):Lattice公司
采用14級(jí)二進(jìn)制CC4060構(gòu)成石英秒脈沖源
2010全球電子峰會(huì):Panel Discussion(上)
Sumco計(jì)劃提升12寸硅片供應(yīng)能力,8寸硅片需求持續(xù)低迷
等華為鴻蒙電腦操作系統(tǒng)ISO鏡像的沒戲了!所有Windows電腦都無法下載安裝
英特爾:推動(dòng)6G變革,驅(qū)動(dòng)未來通信新范式
精密的脈沖振蕩器
英飛凌發(fā)布2025財(cái)年第二季運(yùn)營成果
AIX Reference for Sun Solaris Administrators.part3
AIX Reference for Sun Solaris Administrators.part2
十三種人生感悟 (轉(zhuǎn))
簡單的RC時(shí)鐘
2010全球電子峰會(huì):QuickLogic公司
聚焦新的SHARC處理器系列
英特爾和AMD的CPU被證明與Marvell的CXL產(chǎn)品組合兼容
AIX Reference for Sun Solaris Administrators.part1
肯睿Cloudera通過實(shí)時(shí)分析賦能企業(yè)網(wǎng)絡(luò)安全團(tuán)隊(duì)
帶有備用電源的1Hz時(shí)鐘振蕩器
ADS PowerPC標(biāo)準(zhǔn)試驗(yàn)板的調(diào)試工具,由LauterBach公司發(fā)布
cf卡的問題
射頻功率放大器中的記憶效應(yīng)
零售門店的“芯”機(jī)遇:英特爾為智慧零售提質(zhì)增效
開放原子“園區(qū)行”(深圳站)成功舉辦,開源技術(shù)對(duì)接平臺(tái)助推智慧交通生態(tài)繁榮
男人必看的十部電影——課程系列
我做給學(xué)第們學(xué)ARM用的板子,已批量
2010全球電子峰會(huì):Altera公司
AM29LV160D datasheet
恩智浦發(fā)布第三代成像雷達(dá)處理器,可支持L2+至L4級(jí)自動(dòng)駕駛