一 前言
GCC有很多的編譯選項,警告選項;指定頭文件、庫路徑;優化選項。本文針整理一下GCC的警告選項,主要依據http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html文檔,並加上實際的體驗。
二 基本概述
-w
禁止編譯警告的打印。這個警告不建議使用。大約2012年底,公司代碼進行一次大重構,另外從Codeblock集成開發環境轉向Makefile管理,Makefile里面默認使用了-w,因而代碼一直沒有警告,今年個別項目開發中發現一些代碼筆誤導致的BUG,而這些問題可以從編譯警告中知道。前幾個月,領導安排我來fix這些警告。為了自己,為了后人,不建議使用-w選項。
-Werror
將所有的警告當成錯誤處理。此選項謹慎建議加上。有的開源庫警告很多(大名鼎鼎的ffmpeg也有很多警告呢),一一改掉耗時耗人力,必要性也不大。最后,公司代碼加入了一個開源庫,里面有很多代碼警告,可能領導又安排我來fix了。
-Wfatal-errors
遇到第一個錯誤就停止,減少查找錯誤時間。建議加上。很多人遇到錯誤,沒有意識到從第一個開始排查。不管是編譯錯誤,還是程序運行出錯,從最開始的錯誤查起,是個好的做法。
-Wall
開啟“所有”的警告。強烈建議加上,並推薦該選項成為共識。如case語句沒有default處理,有符號、無符號處理,未使用變量(特別是函數有大量未使用的數組,占用棧空間,測試發現,開辟一個未使用的8MB的數組,程序有coredump),用%d來打印地址,或%s打印int值,等,都可以發出警告。
-Wextra
除-Wall外其它的警告。建議加上。
在GCC編譯時,加上必要的警告選項,可以避免很多低級錯誤引發的問題,我就在實際工程代碼中遇到用“==”來賦值,我自己寫的代碼也出現過把“=”當成判斷的。但是,有些錯誤卻不是用GCC選項能解決的。比如一般項目都會自定義調試信息打印函數,但在處理可變參數類型時,往往不注意。
三 實例分析
C代碼:
#include <stdio.h> int main() { int inum = 10; int a_num; while(inum--) { printf("inum is:%d \n\t",inum); } return 0; }
Makfile:
# compile and lib parameter CC := g++ LIBS := LDFLAGS := DEFINES := INCLUDE := -I. CFLAGS := -fno-common -fmessage-length=0 -Wall \ -fno-exceptions -ffunction-sections \ -fdata-sections -fomit-frame-pointer #CFLAGS += -Werror # link parameter #LIB := libfunc.so LIB := libfunc.a #link $(LIB):test.o $(CC) $(CFLAGS) -shared -o -fPIC -o $@ $^ #compile func.o:test.c $(CC) -c -fPIC $^ -o $@ # clean clean: rm -fr *.o
編譯結果:
➜ gcc git:(master) ✗ make g++ -fno-common -fmessage-length=0 -Wall -fno-exceptions -ffunction-sections -fdata-sections -fomit-frame-pointer -c -o test.o test.c test.c: In function ‘int main()’: test.c:6:13: warning: unused variable ‘a_num’ [-Wunused-variable] int a_num; ^~~~~ g++ -fno-common -fmessage-length=0 -Wall -fno-exceptions -ffunction-sections -fdata-sections -fomit-frame-pointer -shared -o -fPIC -o libfunc.a test.o
假如把CFLAGS += -Werror打開,結果如下所示:
g++ -fno-common -fmessage-length=0 -Wall -fno-exceptions -ffunction-sections -fdata-sections -fomit-frame-pointer -Werror -c -o test.o test.c test.c: In function ‘int main()’: test.c:6:13: error: unused variable ‘a_num’ [-Werror=unused-variable] int a_num; ^~~~~ cc1plus: all warnings being treated as errors <builtin>: recipe for target 'test.o' failed make: *** [test.o] Error 1