1. 程式人生 > 其它 >gcc編譯及其選項詳解、 Gcc的錯誤型別及對策(syntex errror、No such file or directory、Undefined symbol)

gcc編譯及其選項詳解、 Gcc的錯誤型別及對策(syntex errror、No such file or directory、Undefined symbol)

技術標籤:C語言gcc/gdb編譯除錯

gcc編譯及其選項詳解、 Gcc的錯誤型別及對策(syntex errror、No such file or directory、Undefined symbol)

1.簡介:

gcc是gnu旗艦產品,目前基本上就是和unix捆綁在一起分發的。這個東西功能強大,但是有多達上千個選項,其使用者手冊也有將近一萬行.雖然其中的多數選項平時很少用到.但是不管裝軟體還是寫程式,往往都會用到gcc.下面我就gcc最最常用的幾個選項做一個簡要的說明,如果你想對gcc有一個全面的瞭解,比如你想知道在其他非x86平臺上gcc是如何工作的話,你可以用命令:man gcc;

gcc [-c|-S|-E] [-std=standard]

      [-g] [-pg] [-Olevel]

      [-Wwarn...] [-pedantic]

      [-Idir...] [-Ldir...]

      [-Dmacro[=defn]...] [-Umacro]

      [-foption...] [-mmachine-option...]

      [-o outfile] infile...

-c 編譯為目標檔案,不連線庫

-S 編譯為彙編程式碼

-E 預處理.預處理之後的程式碼將送往標準輸出

-Wwarn… 設定警告,可以設定的警告開關很多,通常用-Wall開啟所有的警告

-Olevel 設定優化級別,level可以是0,1,2,3或者s,預設-O0,即不進行優化。.

-Dname=definition… 在命令列上定義巨集,有兩種方式,-Dname或者-Dname=definition.在命令列上設定巨集定義的目的主要是為了在除錯的時候設定一些開關, 而在釋出的時候再關閉或者開啟這些開關即可,當然巨集定義也用來對程式碼進行有選擇地編譯.另外也還有其他的一些作用.

-Uname 取消巨集定義name,作用和上面的正好相反.

-Idir… 把dir加到標頭檔案的搜尋路徑中,而且gcc會在搜尋標準標頭檔案之前先搜尋dir.

-llibrary 在連線的時候搜尋library庫,庫是一些archieve檔案–其成員是目標檔案.如果有檔案引用library,library在命令列的位置應該在那個檔案之後,因此,越底層的庫越要放在後面.比如如果你要連線pcap庫,那麼你就需要使用-lpcap對原始檔進行編譯.

-Ldir… 把dir加到庫檔案的搜尋路徑中,而且gcc會在搜尋標準庫檔案之前先搜尋dir.

-pthread 通過pthreads庫加入對多執行緒的支援,這為預處理和連線設定了標誌.pthread是POSIX指定的標準執行緒庫.

-std=standard 設定採用的標準,該選項是針對C語言的,比如-std=c99表示編譯器遵循C99標準.該選項較少使用.而且有時反而會把你搞糊塗.

-o outfile 指定輸出檔案的檔名,預設為a.out

-mmachine-option… 指定所用的平臺.


2.gcc常用選項總結

2.1 常規選項

1、沒有任何選項:gcc helloworld.c

結果會在與helloworld.c相同的目錄下產生一個a.out的可執行檔案。

2、-o選項,指定輸出檔名:gcc -o helloworld helloworld.c

-o意思是Output即需要指定輸出的可執行檔案的名稱。這裡的名稱為helloworld。

3、-c選項,只編譯,不彙編連線:gcc -c helloworld.c

-c意思就是Compile,產生一個叫helloworld.o的目標檔案

4、-S選項,產生彙編原始檔:gcc -S helloworld.c

-S意思就是aSsemble,產生一個叫helloworld.s的彙編原始檔

5、-E選項,預處理C原始檔:gcc -E helloworld.c

-E意思就是prEprocess。輸出不是送到一個檔案而是標準輸出。當然可以對它進行重定向:

gcc -E helloworld.c > helloworld.txt

2.2 優化選項

  1. -O選項,基本優化:gcc -O helloworld.c

-O意思就是Optimize,產生一個經過優化的叫作a.out的可執行檔案。也可以同時使用-o選項,以指定輸出檔名。如:

gcc -O -o test helloworld.c

即會產生一個叫test的經過優化的可執行檔案。

  1. -O2選項,最大優化:gcc -O2 helloworld.c

產生一個經過最大優化的叫作a.out的可執行檔案。

2.3 除錯選項

  1. -g選項,產生供gdb除錯用的可執行檔案:gcc -g helloworld.c

產生一個叫作a.out的可執行檔案,大小明顯比只用-o選項編譯彙編連線後的檔案大。

  1. -pg選項,產生供gprof剖析用的可執行檔案:gcc -pg helloworld.c

產生一個叫作a.out的執行檔案,大小明顯比用-g選項後產生的檔案還大。


3. Gcc的錯誤型別及對策

Gcc編譯器如果發現源程式中有錯誤,就無法繼續進行,也無法生成最終的可執行檔案。為了便於修改,gcc給出錯誤資訊,我們必須對這些錯誤資訊逐個進行分析、處理,並修改相應的語言,才能保證原始碼的正確編譯連線。gcc給出的錯誤資訊一般可以分為四大類,下面我們分別討論其產生的原因和對策。

第一類∶C語法錯誤

錯誤資訊∶檔案source.c中第n行有語法錯誤(syntex errror)。這種型別的錯誤,一般都是C語言的語法錯誤,應該仔細檢查原始碼檔案中第n行及該行之前的程式,有時也需要對該檔案所包含的標頭檔案進行檢查。有些情況下,一個很簡單的語法錯誤,gcc會給出一大堆錯誤,我們最主要的是要保持清醒的頭腦,不要被其嚇倒,必要的時候再參考一下C語言的基本教材。

第二類∶標頭檔案錯誤

錯誤資訊∶找不到標頭檔案head.h(Can not find include file head.h)。這類錯誤是原始碼檔案中的包含標頭檔案有問題,可能的原因有標頭檔案名錯誤、指定的標頭檔案所在目錄名錯誤等,也可能是錯誤地使用了雙引號和尖括號。

第三類∶檔案庫錯誤

錯誤資訊∶連線程式找不到所需的函式庫,例如∶

ld: -lm: No such file or directory

這類錯誤是與目標檔案相連線的函式庫有錯誤,可能的原因是函式庫名錯誤、指定的函式庫所在目錄名稱錯誤等,檢查的方法是使用find命令在可能的目錄中尋找相應的函式庫名,確定檔案庫及目錄的名稱並修改程式中及編譯選項中的名稱。

第四類∶未定義符號

錯誤資訊∶有未定義的符號(Undefined symbol)。這類錯誤是在連線過程中出現的,可能有兩種原因∶一是使用者自己定義的函式或者全域性變數所在原始碼檔案,沒有被編譯、連線,或者乾脆還沒有定義,這需要使用者根據實際情況修改源程式,給出全域性變數或者函式的定義體;二是未定義的符號是一個標準的庫函式,在源程式中使用了該庫函式,而連線過程中還沒有給定相應的函式庫的名稱,或者是該檔案庫的目錄名稱有問題,這時需要使用檔案庫維護命令ar檢查我們需要的庫函式到底位於哪一個函式庫中,確定之後,修改gcc連線選項中的-l和-L項。

排除編譯、連線過程中的錯誤,應該說這只是程式設計中最簡單、最基本的一個步驟,可以說只是開了個頭。這個過程中的錯誤,只是我們在使用C語言描述一個演算法中所產生的錯誤,是比較容易排除的。我們寫一個程式,到編譯、連線通過為止,應該說剛剛開始,程式在執行過程中所出現的問題,是演算法設計有問題,說得更玄點是對問題的認識和理解不夠,還需要更加深入地測試、除錯和修改。一個程式,稍為複雜的程式,往往要經過多次的編譯、連線和測試、修改。