C/C++编译器的最佳警告级别是什么?

47

你建议不同的C/C++编译器使用什么编译警告级别?

gcc和g++默认级别允许很多问题存在。我发现对我来说最好的警告级别是"-Wall"。我总是尝试消除代码产生的警告,即使是一些关于逻辑优先级规则或者我真正的意图是'if (x=y)'的愚蠢警告。

您喜欢不同编译器的哪些级别,例如Sun CC,aCC(HPUX?),Visual Studio,Intel?

编辑:

我只想指出,我不在gcc/g++上使用“-Werror”(但我确实理解它的实用性),因为我在我的代码中的一些地方使用:

#warning "this is a note to myself"

所有编译器是否都理解 #warning 宏?


1
#warning 不是标准的;我认为 #error 是相当普遍的。 - Mikeage
14个回答

50

这是我在 C++ 代码中使用的一组额外谨慎的标志:

    -g -O -Wall -Weffc++ -pedantic  \
    -pedantic-errors -Wextra -Waggregate-return -Wcast-align \
    -Wcast-qual  -Wchar-subscripts  -Wcomment -Wconversion \
    -Wdisabled-optimization \
    -Werror -Wfloat-equal  -Wformat  -Wformat=2 \
    -Wformat-nonliteral -Wformat-security  \
    -Wformat-y2k \
    -Wimplicit  -Wimport  -Winit-self  -Winline \
    -Winvalid-pch   \
    -Wunsafe-loop-optimizations  -Wlong-long -Wmissing-braces \
    -Wmissing-field-initializers -Wmissing-format-attribute   \
    -Wmissing-include-dirs -Wmissing-noreturn \
    -Wpacked  -Wpadded -Wparentheses  -Wpointer-arith \
    -Wredundant-decls -Wreturn-type \
    -Wsequence-point  -Wshadow -Wsign-compare  -Wstack-protector \
    -Wstrict-aliasing -Wstrict-aliasing=2 -Wswitch  -Wswitch-default \
    -Wswitch-enum -Wtrigraphs  -Wuninitialized \
    -Wunknown-pragmas  -Wunreachable-code -Wunused \
    -Wunused-function  -Wunused-label  -Wunused-parameter \
    -Wunused-value  -Wunused-variable  -Wvariadic-macros \
    -Wvolatile-register-var  -Wwrite-strings

那应该可以让你有所开始。根据项目的不同,您可能需要进行一些调整,以避免来自第三方库的警告(这些库通常对警告不太关心). 例如, Boost 向量/矩阵代码将使 g++ 发出大量警告。

更好的处理这种情况的方法是编写一个围绕 g++ 的包装器,仍然使用调整到最大的警告级别,但允许我们针对特定的文件/行号隐藏它们。我很久以前就写了这样一个工具,并且会在有时间整理后发布它。


1
有人问了一个类似于gcc特定的问题,并且引用了这篇文章。我更新了这个答案,以删除重复的警告(例如,-Wformat=2意味着-Wformat-y2k)。请参见:https://dev59.com/AW445IYBdhLWcg3wAFm0#9862800 - David Stone
g++不会使用“-Wimplicit”进行构建,这是C/ObjC特定的。 - user1244033
1
这里似乎有很多冗余。例如(至少在GCC上)-Wall意味着-Wunused。此外,如果您解释一下这些标志,这个答案会更好。 - Lii

24
在Visual C++中,我使用/W4/WX(将警告视为错误)。 VC还有/Wall选项,但它与标准头文件不兼容。 我选择将警告视为错误,因为这迫使我修复它们。我会修复所有的警告,即使这意味着添加#pragma来忽略警告——这样,我就明确表示我已经知道了这个警告(这样其他开发人员就不会给我发电子邮件提醒)。

2
我们有特定的警告,我们明确不予理会,并且在其他所有内容上实行无警告的编译(无警告)策略。 - David Thornley

14

我相信VC也支持

#pragma message ("note to self")

随着系统的不断扩大,你可能会遇到一个由30名开发人员同时处理的夜间构建版本。在这种情况下,阅读所有自我提示的时间需要数天,即使你全职阅读而不做其他事情,最终也会因为无法跟上进度而崩溃并辞职...

实际上,如果你允许警告信息不断增长,它们的数量很快就会增加。这时候,你将无法发现真正重要的警告信息(如未初始化变量、在构造函数中使用了this指针等)。

这就是为什么我尽量将警告视为错误:大多数情况下,编译器给出的警告都是正确的,如果不正确,我会在代码中进行记录并添加注释。

#pragma warning ( push )
#pragma warning ( 4191 : disable )
// violent code, properly documented
#pragma warning ( pop )

刚刚阅读到他们也有一个warning ( N : suppress )指示符。


10

我倾向于使用-Wall(因为每个人都会犯错误,没有人是完美的),但我不使用-Werror(将警告视为错误),因为有时gcc会发出有关正确的事情的警告(误报)。


1
那么,如果gcc向您抛出100个警告,每次编译时您都会全部检查吗?否则,我不知道您如何处理埋在假阳性堆中的真正警告... - Paulius
1
您可以通过使用此处描述的技术来解决 flex/bison 警告问题:http://wiki.services.openoffice.org/wiki/Writing_warning-free_code - codelogic
2
Paulius,如果它给我100个警告,我会修复掉其中的一些,这样就只剩下几个不需要担心的警告了。使用好的库可以避免出现一大堆警告信息。而且,还要注意代码逻辑。我通常会定期进行"警告清除",将它们全部解决掉 :) - Johannes Schaub - litb
1
我除了使用 -Wall 外,还会加上 -W(又称为 -Wextra),因为它可以捕获一些额外的警告,主要是由于拼写错误和遗忘的代码路径(哎呀,忘记返回值了!)。在编译阶段捕获这些愚蠢的错误非常有帮助。 - strager
1
无论如何,我觉得启用所有警告比仅启用一些但启用-Werror更好,因为否则就无法编译而出现错误。但这似乎是一个非常主观的问题 :) - Johannes Schaub - litb
显示剩余8条评论

8

我同意litb的观点,始终使用-Wall。此外,如果您想确保代码符合规范,还可以使用-pedantic。另一个有用的警告是-Wpadded,特别适用于以字节级别处理联合和结构体的情况。


4

我在进行所有开发时都会打开“将警告视为错误”的选项。

由于我仍在使用VC6进行开发,因此我的代码中有很多#pragma指令(主要是4786)。



3

1
更好的方法是查看GCC手册:http://gcc.gnu.org/onlinedocs/gcc-4.3.2/gcc/Warning-Options.html - strager

3
在GCC中,我倾向于使用-Wall -Wextra -Wwrite-strings -Werror,并且通过std=指定标准。选择的标准取决于项目:主要取决于它需要多么可移植。
我使用-Werror的原因是,即使警告不代表真正的错误,它们也是不可接受的(对我来说)。我宁愿解决导致警告的任何问题,也不想在编译每个程序时都忽略警告。一旦允许编译中出现警告,就很容易错过上次没有出现的警告。
当然,在处理第三方代码时,有时您无法消除警告。这时,我会根据情况决定是否放松-W选项、删除-Werror并编写脚本以检查只出现预期的警告,或者修改第三方代码(如果可能)以“修复”警告或使用编译指示禁用它。

3

我喜欢使用-Wall和严格的原型定义,以及隐式函数定义。这些错误可以非常有用。还有-Wextra,它会捕捉到所有的不同种类的问题,比如你本来打算写条件语句,但不小心写成了语句:

if (something);
   classic_way_to_leak_memory();

在类Unix系统上,您必须遵守用户的 ENV 首选项..因此,他们看到和报告的可能与您所需要的完全不同 :)
我也是一个类型切换狂人,所以除非用户需要,否则我倾向于设置-Fno-strict-aliasing。在经典 C 中进行安全内存管理难以实现。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接