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