一 前言
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 ",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