2013-12-18 69 views
0

我正在研究在Solaris 10中從Sun C 5.9遷移到gcc(GCC)3.4.6的可能缺陷,以便與我們的其他程序保持一致。是否有任何指導或可能存在的缺陷列表,我們應該注意?從Sun C編譯器遷移到gcc

我們已經縮小了與下面的代碼排序的問題(美國稱爲是不好的做法,但長期存在):

char* stringLiteralPointer = "someStringLiteralValue"; 
strcpy(stringLiteralPointer , "anonStringLiteralValue"); //Crash here only with gcc 

可以通過使用-Wwrite串被檢測到這個錯誤,並檢查所有的錯誤。是否還有其他類似的警告我們應該注意到,可能會指出gcc c編譯器和Sun C編譯器中的差異可能導致更多此類可能的運行時錯誤?

+4

我想你的意思是strcpy –

+2

Gcc 3.4.6在編譯器中也很古老。 – Novelocrat

+0

我認爲靜態代碼驗證可以在這種情況下產生很大的好處,我推薦cppcheck,它可以讓您對錯誤代碼有很多瞭解,而不僅僅是遷移錯誤 –

回答

-1

可以通過使用-Wwrite串並檢查所有的錯誤

strlen(stringLiteralPointer , "anonStringLiteralValue"); 

不是C.有效地檢測到這個錯誤我沒有任何標誌(警告)得到這個錯誤:

[Error] too many arguments to function 'strlen' 

是否還有其他類似的警告我們應該知道,可以指出更多的可能的運行時錯誤從g cc c編譯器和Sun C編譯器?

在GCC,檢測到更多的警告,你可以用-Wall-Wextra標誌編譯C99模式(-std = C99)你的代碼。

+1

你已經做出了真實的陳述,但它如何以任何方式回答這個問題? –

+0

@RobKennedy;因爲我的編譯器GCC 4.8.1檢測到沒有任何標誌的錯誤。 – haccks

+2

@RobKennedy:它回答你問的問題。你向我們展示了用兩個參數調用'strlen'的代碼。這真的是你的代碼嗎? –

4

strlen函數只接受一個類型爲const char*的參數(這意味着它將接受非constchar*參數)。

一些較舊的編譯器可能接受函數調用的參數個數不正確。您需要修復代碼。

這是假設您的代碼實際上使用strlen。正如fernando.reyes在評論中建議的那樣,很可能你的意思是strcpy而不是strlen(特別是因爲你不使用結果;調用strlen()而放棄結果沒有多大意義)。

在這種情況下,問題是stringLiteralPointer指向(與數組對象關聯的)字符串文字。試圖修改這樣的數組有未定義的行爲。一些編譯器可能會將字符串文字放在讀/寫內存中,但不應該依賴於此。

此外,解決方案是修復您的代碼。您需要安排stringLiteralPointer指向不是字符串文字的數組。一種方法是使用malloc分配足夠的空間(並確保檢查malloc返回的指針非空)。如果你的指針已經指向字符串,你也可以使用非標準的strdup函數,它試圖分配一個新的字符串讀/寫副本並返回一個指向它的指針。同樣,您需要確認分配成功。

另一種選擇可能是使用數組而不是指針。這:

char *ptr = "literal"; 

導致ptr指向一個字符串,你不允許修改。這:

char arr[] = "literal"; 

使arr數組包含字符串文字的讀/寫副本。

確保您問題中的代碼是您正在編譯的實際代碼。複製並粘貼它,不要重新輸入。 Please read this

更一般地說,gcc有許多選項來啓用額外的警告。如果你用類似的方式編譯你的代碼:

gcc -std=c99 -Wall -Wextra -O3 ... 

你可能會在你的代碼中發現一些有問題的東西。 -std=c99選項告訴gcc(嘗試)符合1999 ISO C標準;如果您的代碼旨在符合C90(通常不正確地稱爲「ANSI C」),請使用-ansi而不是-std=c99-O3選項啓用最大優化級別;這會導致編譯器執行額外的分析,也可以啓用更多警告。

有許多C檢查器比大多數編譯器執行更多的分析。 Lint是原始工具。 Splint(以前稱爲LCLint)是一種現代化的實施方式,可免費獲得here或(可能)通過系統的軟件包管理器。