GCC編譯器介紹
1.什么是編譯器
編譯器是指從高級語言到低級語言的翻譯器,它是一種電腦程序,它可以將用某種編程語言寫成的源代碼(原始語言),轉換成另一種編程語言(目標語言),即計算機或者微型處理器能夠識別的二進制機器代碼(由0和1組成的序列)。
2.GCC編譯器
GCC編譯器是Linux下使用最廣泛的C/C++編譯器,大多數的Linux發行版本都默認安裝,它是一組編譯總工具的總成,軟件包里包含了眾多的工具,按照類型可以分為:
1.C編譯器
2.C++編譯器
3.源碼預處理程序
4.庫文件
3.GCC編譯器的流程
GCC編譯器將源代碼文件轉換為可執行文件需要四個過程
1.預處理(完成宏定義和include文件展開等工作)
2.編譯(根據編譯參數進行不同程度的優化,編譯成匯編代碼)
3.匯編(用匯編器把匯編代碼進一步生成目標代碼)
4.鏈接(用連接器把生成的目標代碼和系統或用戶提供的庫連接起來,生成可執行文件)
GCC編譯器的使用
1.創建源文件
首先,我們在目錄下新建一個名為ccc的文件夾。這個文件夾專門用來存放與C語言相關的文件,例如源文件、目標文件、可執行文件等,它專供我們學習使用。
接下來創建一個空白的 hello.c 源文件,之前的博客已經介紹了文件的創建
cd ccc #進入ccc文件夾
touch hello.c #使用touch命令創建一個名為hello.c的空文件
2.編輯源文件
在Linux下,很多程序員都推崇使用Vim、Emacs、Nano等命令行模式的編輯器,它們功能強大(此前已經介紹了Vi編輯器的用法),但是它們並不容易上手,使用者需要記住很多命令和快捷鍵,所以需要一段時間的學習和適應。因此在這里我使用了Gedit編輯器,Gedit是一款簡單實用的文本編輯器,比Vi容易上手,它和Windows下的編輯器沒有什么區別。
Linux有的發行版可能沒有默認安裝Gedit,這里給出安裝步驟:
sudo apt-add-repository ppa:ubuntu-on-rails/ppa #添加ubuntu的軟件源
sudo apt-get update #更新軟件列表
sudo apt-get install gedit-gmate #安裝
gedit hello.c
首先打開首選項,根據自己的習慣進行編輯器的設置。
之后就可以編輯剛剛創建的源文件了
我們在Gedit中輸入一段簡單的C語言代碼:
按Ctrl+S保存文件,然后關閉Gedit窗口。
更多Gedit編輯器的使用方法見
3.GCC編譯流程的各項參數
gcc -E hello.c -o hello.i #預處理階段 -E,只執行到預編譯。直接輸出預編譯結果。
gcc -S hello.i -o hello.s #編譯階段 -S,只執行到源代碼到匯編代碼的轉換,輸出匯編代碼。
gcc -c hello.s -o hello.o #匯編階段 -c,只執行到編譯,輸出目標文件。
gcc hello.o -o hello #鏈接階段 -o, 指定輸出文件名,可以配合以上三種標簽使用。
文件類型
一談到文件類型,大家就能想到Windows的文件類型,比如.txt、.doc、.bat、.mp3、.exe等,根據文件的后綴就能判斷文件的類型。但在Linux系統中,一個文件是否能被執行,和后綴名沒有太大的關系,與文件的屬性有關,可執行文件沒有統一的后綴,系統從文件的屬性來區分可執行文件和不可執行文件。但是和計算機交流的畢竟還是程序員,對於一個光禿禿沒有后綴的文件來說,沒辦法一眼看出到底是什么文件類型,那么對於編譯過程其實會有一系列的約定俗成的文件后綴,以方便程序員能夠快速知道這個文件到底是什么:gcc則通過后綴來區別輸入文件的類別 。
以下是一些gcc輸入文件后綴說明:
后綴 | 說明 |
---|---|
.c | C語言源文件 |
.s | 匯編語言的程序 |
.h | 源程序所包含的頭文件 |
.i | 預處理后的C程序 |
.ii | 預處理后的C++程序 |
.S | 預處理后的匯編程序 |
.o | 二進制目標文件(未經過鏈接,不能直接執行) |
.cpp .cc .cxx | C++源程序 |
.a | 有目標文件構成的檔案庫文件 |
.m | Objective-C源程序 |
雖然如此,通常在Linux中我們還是會以適當的擴展名來表示文件的種類,下面列舉Linux中幾種常見的擴展名:
擴展名 | 說明 |
---|---|
.sh | 腳本或批處理文件,sh 命令調用缺省 shell 並使用它的語法和標志,因為批處理文件為使用shell寫成的,所以擴展名就編成 .sh |
.tar .zip .tgz | 經過打包的壓縮文件,由於壓縮軟件的不同而取不同的擴展名 |
.html .htm | HTML語法的網頁文件,可以用網頁瀏覽器直接瀏覽 |
.php | PHP語法的網頁文件,可以透過 client 端的瀏覽器來 server 端瀏覽 |
.txt | 純文本文件 |
.so | 類庫文件,在linux環境下,c++編譯得到庫文件后綴包括.so |
.png .xpm .jpg | 圖像文件 |
4.演示
1.預處理之前編寫好的代碼
打開生成的.i文件
預處理后可以看到,和之前的代碼區別很大,增加了許多的內容,但是還依然是文本文件可讀的。增加的這部分內容比如包含的頭文件之類的預處理內容
2.編譯預處理后的代碼
處理完成后的文件類似text
3.匯編編譯后的文件
匯編完成后,可以看出,生成的文件已經是一個二進制文件了,但這個文件不具備執行的權限
4.鏈接並執行
這時生成了一個可執行文件,我們執行hello文件,得到了想要的結果
當然,最簡單的生成可執行文件的寫法為:
gcc hello.c
此時桌面上生成了一個名為a.out的文件(gcc生成的可執行文件名默認為a.out),這就是最終生成的可執行文件,這樣就一次完成了編譯和鏈接的全部過程
如果不想用默認的文件名,可以使用-o選項來自定義文件名,如
gcc hello.c -o b.out
因為Linux下可執行文件的后綴僅僅是一種形式上的,所以可執行文件也可以不帶后綴
gcc hello.c -o b
通過-o選項也可以將可執行文件輸出到其他目錄,並不一定非得在當前目錄下,如:
gcc hello.c -o ./目錄名/b.out
gcc hello.c -o 目錄名/b.out
表示將可執行文件輸出到當前目錄下的其他目錄,./表示當前目錄,如果不寫,默認也是當前目錄
注意:該目錄必須存在,如果不存在,gcc 命令不會自動創建目錄,而是拋出一個錯誤。
如果要讓可執行程序包含調試信息,可以使用-g選項
gcc -g hello.c -o b.out
一般要調試某個程序,為了能清晰地看到調試的每一行代碼、調用的堆棧信息、變量名和函數名等信息,需要調試程序中包含調試信息。gcc中加上-g選項即可在編譯后的程序中保留調試符號信息,事實上,-g選項同樣適用於Cmake、Makefile等工具生成的Linux程序。
5.運行可執行程序
輸入
./a.out
./表示當前目錄,整條命令的意思是運行當前目錄下的 a.out 程序 ,按下回車鍵,程序就開始執行了,它會將輸出結果直接顯示在控制台上。如果程序在其它目錄下,運行程序時還要帶上目錄的名字,如
./目錄名/a.out
目錄名/a.out
注意,如果程序沒有執行權限,可以使用sudo命令來增加權限,如
sudo chmod 777 a.out
Linux系統中,操作文件或目錄的用戶有3種類型:文件所有者、群組用戶、其他用戶。chmod命令最高位表示文件所有着的權限值,中間位表示群組用戶的權限值,最低位表示其他用戶的權限值
權限數值 | 權限 |
---|---|
4 | 當前用戶可以讀取文件內容和瀏覽目錄 |
2 | 當前用戶可以修改文件內容,改變目錄或目錄內文件 |
1 | 當前用戶可以進入目錄,執行文件 |
上述7=4+2+1,因此chmod 777命令可以給文件增加執行權限
調試器GDB簡介
1.GDB是什么?
gdb是GNU開源組織發布的一個強大的Linux下的程序調試工具,相比於VC等IDE調試的優點是具有修復網絡斷點以及恢復鏈接等功能,比BCB的圖形化調試器有更強大的功能。
2.GDB的功能
一般來說,GDB主要幫助你完成下面四個方面的功能:
1、啟動你的程序,可以按照你的自定義的要求隨心所欲的運行程序。
2、可讓被調試的程序在你所指定的調置的斷點處停住。(斷點可以是條件表達式)
3、當程序被停住時,可以檢查此時你的程序中所發生的事。
4、你可以改變你的程序,將一個BUG產生的影響修正從而測試其他BUG。
GDB的具體功能包括:
l 設置斷點
l 監視程序變量的值
l 程序的單步執行
l 顯示、修改變量的值
l 顯示、修改寄存器
l 查看程序的堆棧情況
l 遠程調試
3.GDB的運行
以之前編輯好的hello.c作為測試程序,首先生成可執行程序(為了產生調試信息,-g參數不能缺少)
輸入
gdb -v
查看調試器信息,然后運行gdb
輸入l(list)命令顯示需要編譯調試的源程序
設置斷點
GDB可以通過b(break)命令設置斷點,斷點的設置可以通過函數名、行號、文件名+函數名、文件名+行號以及偏移量、地址等進行設置,格式為:
b 函數名
b 行號
b 文件名:函數名
b 文件名:行號
b +偏移量
b -偏移量
b *地址
如圖斷點先下在第4行,運行后再通過b +1命令使斷點下在第6行
斷點設置時還可以條件斷住,格式為
break 斷點 if 條件。如
break sum if a==1
斷點還可以通過disable/enable臨時停用啟用,格式為
disable 斷點編號
disable 1 #停用斷點1
disable mem 內存區域
disable mem ox1151
enable 斷點編號
enable once 斷點編號(該斷點只啟用一次,程序運行到該斷點並暫停后,該斷點即被禁用)
enable mem 內存區域
刪除和查看斷點
通過 info break 命令可以查看設置的斷點列表
而斷點的刪除命令包括:
delete <斷點id>:刪除指定斷點
delete:刪除所有斷點
clear 函數名
clear 行號:刪除某一行所有斷點
clear 文件名:行號
clear 文件名:函數名
顯示變量
輸入命令“ print 變量 "可以查看變量內容
如果需要一行監控多個變量,可以通過p {var1, var2, var3}
p {a,b,c}
如果要跟蹤變量自動顯示,可以使用display {var1, var2, var3}
display {m,n,f}
顯示寄存器
輸入命令” info reg (i r)”可以顯示寄存器內容
在寄存器名之前加$可以顯示寄存器內容,格式為
p/x $寄存器:十六進制顯示寄存器內容
p $寄存器:顯示寄存器內容
用x命令可以顯示內容內容,格式為
“x/格式 地址” ,如
x $pc:顯示程序指針內容
執行
單步執行:包括next(n)命令和step(s)命令(兩者的區別是next遇到函數不會進入函數內部,step會執行到函數內部)
多步執行:使用continue和run命令,程序遇到斷點后暫停執行;如果沒有斷點,就會一直執行到結束
命令“continue 次數”可以實現使程序繼續執行一定次數的功能
監視點
要想找到變量在何處被改變,可以使用watch命令設置監視點watchpoint,格式為
watch <表達式>:表達式發生變化時暫停執行
watch a
awatch <表達式>:表達式被訪問、改變時暫停執行
waatch 2*a+4
rwatch <表達式>:表達式被訪問時暫停執行
應該注意的是,GDB不能監控一個常量,以下命令會使調試器報錯
watch 1
其它命令
(gdb)set
:設置變量的值
set args arg1 arg2
(gdb)backtrace
:查看函數的調用的棧幀和層級關系,簡寫bt
(gdb)info
:查看函數內部局部變量的數值,簡寫i
info args
(gdb)finish
:結束當前函數,返回到函數調用點
(gdb)undisplay
:取消追蹤觀察變量
undisplay i
(gdb)x
:查看內存x/20xw 顯示20個單元,16進制,4字節每單元
(gdb)run argv[1] argv[2]
:調試時命令行傳參
以上僅列舉了部分GDB常用的調試命令,輸入
(gdb)help
可以查看命令幫助,具體命令查詢在gdb中輸入help + 命令,簡寫h
筆者發現許多同學對gcc編譯器和gdb調試器存在盲點,不知道二者具體的作用因此難以區分二者。gcc編譯器和gdb調試器將成為我們未來學習中的重要工具,有助於提升我們的編程能力。謹希望本文能夠對大家有所幫助。
參考資料
[Linux GCC編譯器和GDB調試器-簡書](Linux GCC編譯器和GDB調試器 - 簡書 (jianshu.com))
其它文獻資料
本博客僅作學習使用,如有侵權請聯系作者