close

轉自:http://wenku.baidu.com/view/01f99435f111f18583d05a47.html

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 語言描述一個演算法中所產生的錯誤,是比較容易排除的。我們寫一個程式,到編譯、連接通過為止,應該說剛剛開始,程式在運行過程中所出現的問題,是演算法設計有問題,說得更玄點是對問題的認識和理解不夠,還需要更加深入地測試、調試和修改。一個程式,稍為複雜的程式,往往要經過多次的編譯、連接和測試、修改。


二、常見錯誤資訊解析與處理

1、預處理時的錯誤資訊

No such file or directory
中文含義:沒有相應檔或目錄
錯誤原因:編譯器的搜索路徑上找不到所需要的檔。該檔可能已在命令列中指定,或在 #include 語句中說明。
處理方法:查看檔案名是否正確,或檔所存放的目錄是否已添加到系統目錄
或連結目錄中。以下是樣例:
#include <stdoi.h> /* 錯誤:檔案名不正確 */
int main (void){
printf ("Hello World!/n");
return 0;
}

上面的程式試圖引入一個不存在的檔‘stdoi.h’ ,這就會引發如下錯誤:
‘stdoi.h: No such file or directory’。而正確的檔案名應該是‘stdio.h’

macro or '#include' recursion too deep
中文含義:宏或'#include' 遞迴太深
錯誤原因:語句 #include 嵌套太深。當前置處理器遇到太多嵌套的 #include 指令時,會導致此錯誤。通常該錯誤由兩個或多個檔進行相互引用時,會引發無限遞迴。如:
/* foo.h */
#include "bar.h"
...
/* bar.h */
#include "foo.h"
...

解決方法是確保各檔沒有互相引用。

invalid preprocessing directive #...
中文含義:非法的預處理命令#...
錯誤原因:該錯誤指明前置處理器遇到了不可識別的 # 命令。如:
#if FOO
int x = 1;
#elseif BAR /*
應寫成 #elif */
int x = 2;
#else
int x = 3;
#endif

前置處理器語法在 #if 塊中需要 #elif 而不是 "else if" 條件,也不是
#elseif

warning: This file includes at least one deprecated or antiquated header.
中文含義:警告:檔中至少引用了一個已廢棄的或過時的標頭檔
C++ 程式中引用了舊式的標頭檔庫,如’iostream.h’, 在現代C++庫標頭檔沒有’.h’副檔名。舊標頭檔導入其函數到頂層全域名字空間,對C++需要使用std:: 名字空間。當然,對舊式風格的頭
檔仍然支援,所以對現有程式會繼續編譯,只是給出警告。如:
#include <iostream.h> /* 舊式風格 */
int main (void){
cout << "Hello World!/n";
return 0;
}

‘iostream.h’應改寫為 #include <iostream> std::cout

unterminated '#if' conditional
中文含義:'#if' 語句條件沒有終止
錯誤原因:缺少 #endif 語句
2、編譯時的錯誤資訊
'variable' undeclared (first use in this function)
中文含義:變數'variable' 沒有聲明(第一次使用此變數)
解決方法:在使用前聲明該變數。
解析:在 C C++中,變數必須先聲明後使用。如:
int main (void){
int i;
j = 0; /* j
變數沒聲明 */
return j;
}

此例中,j 是沒經聲明的變數,所以將觸發錯誤:'j' undeclared.

parse error before '...'
中文含義:在 'XXX' 語句前解析錯誤
錯誤原因:語法錯誤
解析:通常是編譯器遇到了未期望的輸入。如:不合語法的字串序列。此錯誤也可能因為丟失花括弧、園括弧或分號,或寫了非法的保留字而引發。
#include <stdio.h>
int main (void){
4
printf ("Hello ") /*
丟失分號 */
printf ("World!/n");
return 0;
}

conflicting types for 'Alex'
中文含義:對 'Alex' 變數存在突出類型
錯誤原因:前面可能已對 'Alex' 聲明了其它資料類型。例如:存在兩條語句分別聲明了兩次'Alex'變數為兩種枚舉 (enum) 類型。

two or more data types in declaration specifiers
中文含義:在聲明識別字中存在多種資料類型
最容易出現這樣的錯誤,原因是在程式裡少了個號。有可能在標頭檔裡,也有可能在本檔中(最容易出錯的是在結構體中忘了)。

too many types in declaration
中文含義:在聲明中定義太多的類型
1.是否多次包含著個標頭檔?檢查一下例如:
#ifndef TConfigH
#define TConfigH
#endif //
是否少了這個
2.看下將長語句分為多行時,與下一行語句間是否少了邏輯運算子關係,關係運算符之類的符號

warning: comparison between pointer and integer
中文含義:警告:對指針和整型值進行比較
可能沒問題。此警告通常是由'if (strstr(line,"word") != NULL )' 之類的strstr 函數返回指針或空值。

subscripted value is neither array nor pointer
中文含義:下標值不符合陣列或指標要求
錯誤原因:企圖使用可變的變數作為下標

loppyto.c:782: parse error at end of input
中文含義:在檔案結尾部解析錯誤
floppyto.c 是程式檔案名, 782 是錯誤行數,但該數位大於檔長度。錯誤原因:
存在沒配對的花括弧{}或注解 /* */
#include <stdio.h>
int main (void) {
if (1) {
5
printf ("Hello World!/n");
return 0; /*
花括弧不匹配 */
}


parse error before 'printf'
中文含義:在'printf' 之前解析錯誤
錯誤原因:在該語句之前缺少分號 ';'

warning: implicit declaration of function '...'
中文含義:警告:與函數 XXX 的隱式聲明不相符
錯誤原因:該錯誤是因為使用的函數沒有原型聲明而產生。產生的因為可以是導入錯誤的標頭檔,或忘記提供函數原型。如:
int main (void){
printf ("Hello World!/n"); /*
沒有標頭檔 */
return 0;
}

程式中沒有導入系統標頭檔’stdio.h’,所以也就不存在 printf 的原型聲明。改正方法:在程式最前面加入一行語句: #include <stdio.h>

unterminated string or character constant
中文含義:未終止的字串或字元常量
錯誤原因:該錯誤是因為使用字串或字元常量缺少配對的引號而產生。對字符而言,應使用成對的單引號,而對字串,應使用成對的雙引號。
#include <stdio.h>
int main (void){
printf ("Hello World!/n); /*
缺少閉雙引號*/
return 0;
}


character constant too long
中文含義:字元常量太長
錯誤原因:在 C C++中,字元常量是由單引號封裝起來的單個字元,並且有相應的ASCII 值。如 'a' 對應的ASCII 67, '/n' 對應的ASCII 10。本錯誤是因為使用單引號封裝了多於一個字元而引發。如:
#include <stdio.h>
int main (void){
printf ('Hello World!/n'); /*
錯誤的封裝 */
return 0;
}

多字元組成的是字串,應用雙引號封裝。對上例,應改寫成: "Hello World!"

warning: initialization makes integer from pointer without a cast
中文含義:警告:初始化過程中不能從指標到整型數進行轉換
錯誤原因:該錯誤指示在整型數環境中誤用了指針。從技術上,可以在指標和整型數之間相互轉換,但這很少用在外部系統級應用程式中。通常,此類警告是在使用了指標而沒有釋放該指標而引發。(如語句寫成int i = p 而不是int i =*p,其中p 是指針)。該警告在類型char char *之間轉換時也可能引發,因為char 也是整數類型。
int main (void){
char c = "/n"; /*
不正確 */
return 0;
}

變數 c char 類型,而 "/n" 是字串且會被系統認為是 const char * 指標(將佔用 2-位元組記憶體,包括 '/0',因為字串沒有結束字元)。類似的錯誤也會發生在對宏 NULL 的誤用:
#include <stdlib.h>
int main (void){
int i = NULL; /*
不正確 */
return 0;
}

C ‘stdlib.h’中,宏 NULL 被定義為 ((void *)0) ,它只能用在指針環境中。

dereferencing pointer to incomplete type
中文含義:間接引用指針為不合適的類型
錯誤原因:程式試圖通過指標訪問一個沒有事先聲明的結構體內元素。在CC++中,在聲明指向結構的指標時,應先聲明結構體。
struct btree * data;
int main (void){
data->size = 0; /*
不合適的類型 */
return 0;
}

此程式使用 btree 結構 data 的前向聲明。然而,在指標間接獨立訪問記憶體前,需要定義該結構。

warning: unknown escape sequence '...'
中文含義:警告:未知的轉義序列
錯誤原因:使用了不正確的轉義字元。合法的轉義字元序列如下:
/n 新行 /t 定位字元
/b 回退 /r 回車
/f 換頁 /v 垂直製錶
7
/a
警告 (鈴聲)
組合字元 //, /', /" /? 表示相應的獨立字元。轉義序列也可用八進制碼
/0--/377 和十六進位碼 /0x00--/0xFF 來表示。
#include <stdio.h>
int main (void){
printf ("HELLO WORLD!/N"); /* /N
錯誤 */
return 0;
}


warning: suggest parentheses around assignment used as truth value
中文含義:警告:建議用圓括號括上用於邏輯值的賦值運算式
錯誤原因:該警告強調潛在的語意錯誤,程式在條件陳述式或其它邏輯運算式測試中使用了賦值操作符 ‘=’ 而不是比較操作符 ‘= =’ 。當然在語法上,賦值操作符可作為邏輯值使用,但在實踐中很少用。
#include <stdio.h>
int main (void){
int i = 0;
if (i = 1) { /* =
應該是 == */
printf ("unexpected result/n");
}
return 0;
}


warning: control reaches end of non-void function
中文含義:警告:控制到達非void 函數末端。
錯誤原因:若一個函數已聲明為有返回資料類型(如int double),那麼就必須在函數中的適當位置(所有可能的結束點)使用return 語句返回相應類型的值。否則,就屬於不是良好定義的函數。若函式宣告為void,則不需要return 語句。
#include <stdio.h>
int display (const char * str){
printf ("%s/n", str);
}

以上程式在 display 函數的尾部沒有返回語句,但它又聲明為返回 int 類型。可以通過添加 return 0; 之類的語句加以解決。當使用 gcc 時,C 程式中的 main 函數必須返回一個 int 型資料(用於表明程式的退出狀態)

warning: unused variable '...'
中文含義:警告:存在從未使用的變數 XXX

warning: unused parameter '...'
中文含義:警告:存在從未使用的參數 XXX
錯誤原因:該警告指示存在已聲明為局部的變數或函數參數,但在其它地方並沒使用過它。沒使用過的變數可能會導致程式性錯誤,如偶爾在預期的位置上寫了不同的變數名。
int foo (int k, char * p){
int i, j;
j = k;
return j;
}

在本程式中,變數 i 和參數 p 從沒使用過。

warning: passing arg of ... as ... due to prototype
中文含義:警告:傳送 XX 參數為XXX,但原型不匹配。
錯誤原因:該警告指示在調用函數時,存在與聲明的參數類型原型不一致的情況。

warning: passing arg 1 of 'cpystr' makes integer from pointer
中文含義:警告:函數的參數1 存在參數不匹配,即無法進行類型轉換
錯誤原因:類型轉換不匹配下面的樣例就存在這方面的問題:
void cpystr( char item);
main(){
char src[]="martin leslie";
cpystr(src);
}

cpystr(char item){ }
函數應該寫成如下類似的格式:
void cpystr( char item[]);
main(){
char src[]="martin leslie";
cpystr(src);
}

cpystr(char item[]){ }

warning: assignment of read-only location
中文含義:警告:對唯讀變數進行賦值。
錯誤原因:檢查賦值的變數是否已用 const 修飾或已被聲明為常量。

warning: cast discards qualifiers from pointer target type
中文含義:警告:在指標目標類型中存在不合適的轉換限定詞。

warning: assignment discards qualifiers ...
中文含義:警告:賦值丟棄限定詞 XXX

warning: initialization discards qualifiers ...
中文含義:警告:初始化丟棄限定詞 XXX

warning: return discards qualifiers ...
中文含義:警告:返回值丟棄限定詞 XXX
錯誤原因:對指標的不正確使用了違法的限定詞。檢查賦值的變數是否已用const 修飾或已被聲明為常量。若指針被限制為 const 則該指針不能被修改,且只能被用於向其它指針賦值。
char *f (const char *s){
*s = '/0'; /*
向唯讀數據賦值 */
return s; /*
將會丟棄常量,即並不能被返回 */
}

該程式試圖修改常量資料,並在返回值中使用常量屬性參數而導致丟棄。

initializer element is not a constant
中文含義:初始化元素不是常量。
錯誤原因:在C 中,全域變數只能在初始化是賦值常量,如數值、NULL 或字符串常量。若使用了非常量值則會引發此錯誤。
#include <stdio.h>
FILE *stream = stdout; /*
不是常量 */
int i = 10;
int j = 2 * i; /*
不是常量 */
int main (void){
fprintf (stream, "Hello World!/n");
return 0;
}

注意:在C++中則允許在初始化中使用非常量資料。


3、連結時的錯誤資訊
file not recognized: File format not recognized
中文含義:文件不可識別:檔案格式不可識別。
錯誤原因:檔副檔名不是 ‘.c’
#include <stdio.h>
int main (void){
printf ("Hello World!/n");
return 0;
}

若上述檔保存為 ‘hello’ 但沒有副檔名,則編譯時會給出如下錯誤:

$ gcc -Wall hello
hello: file not recognized: File format not
recognized
collect2: ld returned 1 exit status

解決方案是將文件重命名為帶合適的副檔名。對本例可重命名為 ‘hello.c’.


undefined reference to 'foo' collect2: ld returned 1 exit status
中文含義:沒定義對'foo' 的引用。
錯誤原因:程式中使用了在本檔和其它庫中沒有定義的函數或變數。有可能是丟失了程式庫,或使用了不正確的名字。
在此例中,’collect2’ 是連結程式的一部分。
int foo(void);
int main (void){
foo();
return 0;
}


/usr/lib/crt1.o(.text+0x18): undefined reference to 'main'
中文含義:沒定義對main 函數的引用
錯誤原因:程式中缺少 main()函數。


/usr/lib/crt0.o: Undefined symbol _main referenced from text segment
中文含義:從文本段引用沒定義的_main 符號
錯誤原因:缺少 main()函數但實際上有,為什麼?
1.在標頭檔中可能存在語法錯誤;
2.C 原始檔案中可能缺少gcc 命令


Undefined symbol _initscr referenced from text segment
中文含義:從文本段引用沒定義的_initscr 符號
錯誤原因:調用了一個函數,但並沒有該函數,或在#include 語句中沒有包含
該函數的庫。


4、運行時的錯誤資訊
error while loading shared libraries:cannot open shared object file: No such file or directory
中文含義:裝載共用庫是出錯:不能打開共用物件檔:不存在該檔或目錄
錯誤原因:程式中使用了共用庫,但程式啟動時通過動態連結找不到所需的共
享庫文件。如果確定存在,則請修改共用類庫搜索路徑變數值LD_LIBRARY_PATH

Segmentation fault
中文含義:分段錯誤,匯流排錯誤
錯誤原因:企圖訪問受保護的內容或覆蓋重要的資料! 它指明記憶體訪問錯誤。
通常的原因如下:
1、反向引用一個空指標或沒初始化的指標;
2、超出陣列訪問的下標;
3、對 malloc, free 和相關函數不正確的使用;
4、使用 scanf 時的參數(數量、類型)不正確。

floating point exception
中文含義:浮點運算異常
錯誤原因:這是個算數運算異常。如除數為0,上溢、下溢或非法的操作(如對-1 求平方根)。

Illegal instruction
中文含義:非法指令
錯誤原因:當系統遇到非法的機器指令時,產生此錯誤。通常此類錯誤是在源代碼已編譯成特定機器的目標代碼後,又在其它類型的機器上運行時發生。

arrow
arrow
    文章標籤
    GCC
    全站熱搜
    創作者介紹
    創作者 立你斯 的頭像
    立你斯

    立你斯學習記錄

    立你斯 發表在 痞客邦 留言(0) 人氣()