【1】GCC 編譯器
(1)GNU 工具
編譯工具:把一個源程序編譯為一個可執行程序
調試工具:能對執行程序進行源碼或匯編級調試
軟件工程工具:用于協助多人開發或大型軟件項目的管理,如 make、CVS、Subvision其他工具:用于把多個目標文件鏈接成可執行文件的鏈接器,或者用作格式轉換的工
具。
(2)部分相關資源
//www.gnu.org/
//gcc.gnu.org/
//www.kernel.org/
//www.linux.org/
//www.linuxdevices.com/
//sourceforge.net/index.php
(3)GCC 簡介
全稱為 GNU CC ,GNU 項目中符合 ANSI C 標準的編譯系統
編譯如 C、C++、Object C、Java、Fortran、Pascal、Modula-3 和 Ada 等多種語言
GCC 是可以在多種硬體平臺上編譯出可執行程序的超級編譯器,其執行效率與一般的編譯器相比平均效率要高 20%~30%
一個交叉平臺編譯器 ,適合在嵌入式領域的開發編譯 gcc 所支持后綴名解釋
.c C 原始程序
.C/.cc/.cxx C++原始程序
.m Objective-C 原始程序
.i 已經過預處理的 C 原始程序
.ii 已經過預處理的 C++原始程序
.s/.S 匯編語言原始程序
.h 預處理文件(頭文件)
.o 目標文件
.a/.so 編譯后的庫文件
(4)GCC 編譯器的版本
GNU Compiler Collection
C, C++, Objective-C, Fortran, Java, Ada
//gcc.gnu.org
(5)編譯器的主要組件
1)分析器:分析器將源語言程序代碼轉換為匯編語言。因為要從一種格式轉換為另一
種格式(C 到匯編),所以分析 2)器需要知道目標機器的匯編語言。
3)匯編器:匯編器將匯編語言代碼轉換為 CPU 可以執行字節碼。
4)鏈接器:鏈接器將匯編器生成的單獨的目標文件組合成可執行的應用程序。鏈接器需要知道這種目標格式以便工作。
5)標準 C 庫:核心的 C 函數都有一個主要的 C 庫來提供。如果在應用程序中用到了 C 庫中的函數,這個庫就會通過鏈接器和源代碼連接來生成最終的可執行程序。
(6)GCC 的基本用法和選項
Gcc 最基本的用法是∶gcc [options] [filenames]
-c,只編譯,不連接成為可執行文件,編譯器只是由輸入的.c 等源代碼文件生成.o為后綴的目標文件,通常用于編譯不包含主程序的子程序文件。
-o output_filename,確定輸出文件的名稱為 output_filename,同時這個名稱不能和源文件同名。如果不給出這個選項,gcc 就給出預設的可執行文件 a.out。
-g,產生符號調試工具(GNU 的 gdb)所必要的符號資訊,要想對源代碼進行調試,我們就必須加入這個選項。
-O,對程序進行優化編譯、連接,采用這個選項,整個源代碼會在編譯、連接過程中進行優化處理,這樣產生的可執行文件的執行效率可以提高,
但是,編譯、連接的速度就相應地要慢一些。
-O2,比-O 更好的優化編譯、連接,當然整個編譯、連接過程會更慢。
-I dirname,將 dirname 所指出的目錄加入到程序頭文件目錄列表中,是在預編譯過程中使用的參數。
-L dirname,將 dirname 所指出的目錄加入到程序函數檔案庫文件的目錄列表中,是在鏈接過程中使用的參數。
(7)GCC 的錯誤類型及對策
1)第一類∶C 語法錯誤
錯誤信息∶文件 source.c 中第 n 行有語法錯誤(syntex errror)。
有些情況下,一個很簡單的語法錯誤,gcc 會給出一大堆錯誤,我們最主要的是要保持清醒的頭腦,
不要被其嚇倒,必要的時候再參考一下 C 語言的基本教材。
2)第二類∶頭文件錯誤
錯誤信息∶找不到頭文件 head.h(Can not find include file head.h)。
這類錯誤是源代碼文件中的包含頭文件有問題,可能的原因有頭文件名錯誤、指定的頭文件所在目錄名錯誤等,
也可能是錯誤地使用了雙引號和尖括號。
3)第三類∶檔案庫錯誤
錯誤信息∶鏈接程序找不到所需的函數庫(ld: -lm: No such file or directory )。
這類錯誤是與目標文件相連接的函數庫有錯誤,可能的原因是函數庫名錯誤、指定的函數庫所在目錄名稱錯誤等,
檢查的方法是使用 find 命令在可能的目錄中尋找相應的函數庫名,確定檔案庫及目錄的名稱并修改程序中及編譯選項中的名稱。
4)第四類∶未定義符號
錯誤信息∶有未定義的符號(Undefined symbol)。這類錯誤是在連接過程中出現的,可能有兩種原因∶
一是使用者自己定義的函數或者全局變量所在源代碼文件,沒有被編譯、連接,或者干脆還沒有定義,
這需要使用者根據實際情況修改源程序,給出全局變量或者函數的定義體;
二是未定義的符號是一個標準的庫函數,在源程序中使用了該庫函數,而連接過程中還沒有給定相應的函數庫的名稱,
或者是該檔案庫的目錄名稱有問題,這時需要使用檔案庫維護命令 ar 檢查我們需要的庫函數到底位于哪一個函數庫中,
確定之后,修改 gcc 連接選項中的-l 和-L 項。
(8)GCC 使用實例
#include
int main(void)
{
int i,j;
j=0;
i=j+1;
printf(“hello,world\n”);
printf(“the result is %d\n”,i);
}
編譯:
執行:
$ gcc –o test test.c
$ ./test
查看更詳細的信息:
$ gcc –v –o test test.c
(9)GCC 編譯過程
GCC 的編譯流程分為四個步驟:
預處理(Pre-Processing)
編譯(Compiling)
匯編(Assembling)
鏈接(Linking)
(10)生成預處理代碼
$ gcc –E test.c -o test.i
用 wc 命令,查看這兩個階段代碼大小: $ wc test.c test.cpp
916127test.c
842 193416498 test.cpp
851 195016625 總用量
test.i 比 test.c 增加了很多內容,主要是放在系統提供的 include 文件中的。(11)生成匯編代碼
檢查語法錯誤,并生成匯編文件
$ gcc –S test.c –o test.s
(12)生成目標代碼
方法一,用 gcc 直接從 C 源代碼中生成目標代碼:
$ gcc –c test.s –o test.o
方法二,用匯編器從匯編代碼生成目標代碼:
$ as test.s –o test.o
(13)生成可執行程序
將目標程序鏈接庫資源,生成可執行程序
$ gcc test.s –o test
./test
【2】GDB 調試工具
(1) 調試器--Gdb 調試流程
首先使用 gcc 對 test.c 進行編譯,注意一定要加上選項‘-g’
# gcc -g test.c -o test
# gdb test
(2) Gdb 調試流程
查看文件
(gdb) l
設置斷點
(gdb) b 6
查看斷點情況
(gdb) info b
運行代碼
(gdb) r
查看變量值
(gdb) p n
單步運行
(gdb) n
(gdb) s
恢復程序運行
(gdb) c
幫助
(gdb) help [command]
(3)Gdb 的使用切記點
在 gcc 編譯選項中一定要加入‘-g’。
只有在代碼處于“運行”或“暫停”狀態時才能查看變量值。
設置斷點后程序在指定行之前停止
(4)Gdb 調試
運行被調試程序,設置所有的能影響該程序的參數和變量。
保證被調試程序在指定的條件下停止運行。
當被調試程序停止時,讓開發工程師檢查發生了什么。
根據每次調試器的提示信息來做響應的改變,以便修正某個錯誤引起的問題