用于启用彻底且详细的 g++ 的标志警告
通常,在 gcc
下的 C 语言中,我会从以下一组警告标志开始(从多个源痛苦地组装而成):
-Wall -Wextra -Wformat-nonliteral -Wcast-align -Wpointer-arith -Wbad-function-cast \
-Wmissing-prototypes -Wstrict-prototypes -Wmissing-declarations -Winline -Wundef \
-Wnested-externs -Wcast-qual -Wshadow -Wwrite-strings -Wno-unused-parameter \
-Wfloat-equal -pedantic -ansi
我将使用这组警告构建(至少是我的调试版本)并修复我所遇到的所有问题。可能可以(通常是一切),然后仅删除不相关或不可修复的标志(几乎从来没有这种情况)。有时,如果我在编译时必须离开,我还会添加 -Werror
。
我刚刚开始学习 C++(是的,我落后了 15 年),并且我想以正确的方式开始。
我的问题是:是否有人在 g++
下为 C++ 预编译了一组类似的完整警告标志? (我知道其中很多都是一样的。)
Often in C under gcc
, I will start with the following set of warning flags (painfully assembled from multiple sources):
-Wall -Wextra -Wformat-nonliteral -Wcast-align -Wpointer-arith -Wbad-function-cast \
-Wmissing-prototypes -Wstrict-prototypes -Wmissing-declarations -Winline -Wundef \
-Wnested-externs -Wcast-qual -Wshadow -Wwrite-strings -Wno-unused-parameter \
-Wfloat-equal -pedantic -ansi
I will build (at least my debug versions) with this set of warnings and fix everything I possibly can (usually everything), and then only remove flags if they are either not relevant or not fixable (almost never the case). Sometimes, I'll also add -Werror
if I have to step away while compiling.
I'm just picking up C++ (yes, I'm 15 years behind the times), and I'd like to start off on the right foot.
My question is: Does someone have a precompiled similar set of complete warning flags for C++ under g++
? (I know many of them will be the same.)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我浏览了一下,发现应该得到最高级别警告的最小包含集。然后,我从该列表中删除了一组警告,我认为这些警告实际上并不表明正在发生不良情况,或者有太多误报无法在实际构建中使用。我评论了为什么我排除的每个人都被排除在外。这是我最后一组建议警告:
-pedantic -Wall -Wextra -Wcast-align -Wcast-qual -Wctor-dtor-privacy -Wdisabled-optimization -Wformat=2 -Winit-self -Wlogic-op -Wmissing -声明 -Wmissing-include-dirs -Wno except -Wold-style-cast -Woverloaded-virtual -Wredundant-decls -Wshadow -Wsign-conversion -Wsign-promo -Wstrict-null-sentinel -Wstrict-overflow=5 -Wswitch-default -Wundef -Werror -Wno-unused
存在的可疑警告:
我包含
-Wno-unused
因为我经常有我知道的变量稍后会使用,但还没有编写该功能。
删除有关警告可以让我以我喜欢的风格写作
偶尔推迟事情的实施。很有用
每隔一段时间就将其关闭以确保没有任何滑落
-Wdisabled-optimization
似乎是一个强烈的用户偏好环境。我刚刚将这个添加到我的构建中(仅适用于优化构建
出于显而易见的原因)并且它没有出现任何结果,所以它没有
似乎是一个特别闲聊的警告,至少对于我的编码方式来说是这样。
我包含它(即使触发此警告的代码不是
必然是错误的)因为我相信使用我的工具来工作
反对他们。如果 gcc 告诉我它无法优化代码
对于我写的方式,那么我应该考虑重写它。我怀疑
触发此警告的代码可能会受益于更多
模块化,无论如何,所以虽然代码在技术上没有错误
(可能),从风格上来说可能是这样。
-Wfloat-equal
警告安全相等比较(特别是,与非计算值-1)进行比较。我的代码中的一个例子
我使用它的地方是我有一个浮点向量。我经历过这个
向量,并且有一些元素我无法评估它们是什么
应该是,所以我将它们设置为-1.0f(因为我的问题只使用
正数,-1 超出域)。我稍后会经历并
更新-1.0f 值。它不容易适应不同的情况
操作方法。我怀疑大多数人都没有这个
问题,浮点数的精确数字的比较是
可能是一个错误,所以我将其包含在默认列表中。
-Wold-style-cast
在我使用的库代码中存在很多误报。特别是,网络中使用的 htonl 系列函数以及我正在使用的 Rijndael (AES) 加密实现具有旧式强制转换,它会警告我这一点。我打算替换这两个,但我不确定我的代码中是否还有其他内容会抱怨。不过,大多数用户可能应该默认启用此功能。-Wsign-conversion
是一个艰难的任务(几乎没有成功)列表)。在我的代码中打开它会产生大量警告
(100+)。他们几乎所有人都是无辜的。然而,我已经
在我不确定的地方小心使用有符号整数,尽管对于
我的特定问题领域,我通常会得到一点效率
由于整数数量较多,使用无符号值增加
我做的部门。我牺牲了这个效率,因为我担心
关于意外地将有符号整数提升为无符号整数,然后
除法(与加法、减法不同,这是不安全的)
乘法)。打开这个警告可以让我安全地改变
我的大部分变量都为无符号类型,并在某些变量中添加了一些转换
其他地方。目前使用起来有点困难,因为有警告
是不是很聪明。例如,如果您执行
unsigned Short + (integral
,该结果被隐式提升为 int。它常量表达式)
如果您将该值分配给,则警告潜在的符号问题
unsigned
或unsigned short
,即使它是安全的。这是对于几乎所有用户来说绝对是最可选的警告。
-Wsign-promo
:请参阅-Wsign-conversion
。-Wswitch-default
似乎毫无意义(你并不总是想要默认值如果您已明确列举了所有可能性,则为这种情况)。然而,
打开这个警告可以强制执行一些可能是好的事情
主意。对于您明确想要忽略除以下所有内容的情况
列出的可能性(但其他数字也是可能的),然后输入
在
default: break;
中使其明确。如果你显式枚举所有可能性,然后打开此警告将有助于确保
你放了像断言(假)这样的东西来确保你已经
实际上涵盖了所有可能的选择。它可以让你明确地
你的问题的范围是什么,并以编程方式强制执行。
然而,你必须小心坚持断言(假)
到处。这比默认情况下什么都不做要好,但是
与通常的断言一样,它在发布版本中不起作用。在其他方面
换句话说,你不能依赖它来验证你得到的数字,
例如,您没有绝对的网络连接或数据库
控制。例外或提前返回是最好的方法
处理这个问题(但仍然要求你有一个默认情况!)。
-Werror
对我来说很重要。当编译大量的在具有多个目标的多线程构建中编写代码,很容易
警告溜走。将警告转化为错误可确保我
注意它们。
还有一组警告未包含在上面的列表中,因为我发现它们没有用。这些是警告和我对为什么不将它们包含在默认列表中的评论:
不存在的警告:
-Wabi
是不需要的,因为我'我不合并来自不同编译器的二进制文件。无论如何,我尝试用它进行编译,但它没有触发,所以它看起来并没有不必要的冗长。-Waggregate-return
我不认为是错误。为了例如,当在向量上使用基于范围的 for 循环时会触发
类。返回值优化应该考虑到任何
这样做的负面影响。
-Wconversion
在此代码上触发:short n = 0; n += 2;
的隐式转换为 int 会在转换时引发警告
返回到其目标类型。
-Weffc++
如果所有数据成员未初始化,则包含警告在初始化列表中。我故意不这样做
情况下,因此警告集太混乱而无用。它是
有助于每隔一段时间打开并扫描其他警告,
不过(例如基类的非虚拟析构函数)。这会
作为警告集合(如
-Wall
)更有用,而不是单独一个警告。
-Winline
不存在,因为我不使用 inline 关键字优化目的,只是为了在标头中内联定义函数。我
不关心优化器是否真的内联它。此警告还
如果无法内联类主体中声明的函数,则会抱怨
(例如空的虚拟析构函数)。
-Winvalid-pch
丢失,因为我不使用预编译头。-Wmissing-format-attribute
未使用,因为我不使用 gnu扩展。
-Wsuggest-attribute
和其他几个相同
可能值得注意的是
-Wno-long-long
,我有不需要。我使用
-std=c++0x
进行编译(GCC 4.7 中的-std=c++11
),其中包括
long long
整数类型。那些卡在 C++98 上的 /C++03 可能会考虑从警告列表中添加该排除项。
-Wnormalized=nfc
已经是默认选项,并且看起来是最好的。
-Wpadded
偶尔会打开,以优化布局类,但它不会保留,因为并非所有类都有足够的
元素以删除末尾的填充。理论上我可以得到一些
“免费”的额外变量,但不值得付出额外的努力
维持这一点(如果我的班级人数发生变化,则不容易删除
那些以前的自由变量)。
-Wstack-protector
未使用,因为我不使用-fstack-protector
-Wstrict-aliasing=3
由-Wall
打开,并且是最准确,但看起来 1 级和 2 级给出了更多警告。在
理论上,较低的级别是“更强”的警告,但其代价是
更多误报。我自己的测试代码在所有 3 下都编译干净
-Wswitch-enum
不是我想要的行为。我不想处理明确地每个 switch 语句。如果语言是有用的
有某种机制可以在指定的 switch 语句上激活它
(以确保将来对枚举的更改在任何地方都得到处理
他们需要这样做),但这对于“全有或全无”来说太过分了
设置。
-Wunsafe-loop-optimizations
导致太多虚假警告。它定期应用此方法并手动验证可能会很有用
结果。例如,当我
循环遍历向量中的所有元素以应用一组函数
它们(使用基于范围的 for 循环)。这也是对大家的警告
const std::string 的 const 数组的构造函数(其中 this 不是
用户代码中的循环)。
-Wzero-as-null-pointer-constant
和-Wuseless-cast
是仅 GCC-4.7 警告,我将在转换到 GCC 4.7 时添加。
作为一些研究的结果,我已经向 gcc 提交了一些错误报告/增强请求,因此希望我最终能够将更多警告从“不包括”列表添加到“包括”列表。该列表包括该线程中提到的所有警告(加上我认为一些额外的警告)。本文中未明确提及的许多警告已作为我提到的另一个警告的一部分包含在内。如果有人注意到本文完全排除了任何警告,请告诉我。
编辑:看起来我错过了几个(我现在已经添加了)。实际上,http://gcc.gnu.org 上还有一个隐藏得很好的页面。 一般警告选项 和 C++ 选项(向下滚动到底部查看警告)
I went through and found the minimal set of includes that should get the maximum level of warning. I then removed from that list the set of warnings that I feel do not actually indicate something bad is happening, or else have too many false positives to be used in a real build. I commented as to why each of the ones I excluded were excluded. This is my final set of suggested warnings:
-pedantic -Wall -Wextra -Wcast-align -Wcast-qual -Wctor-dtor-privacy -Wdisabled-optimization -Wformat=2 -Winit-self -Wlogical-op -Wmissing-declarations -Wmissing-include-dirs -Wnoexcept -Wold-style-cast -Woverloaded-virtual -Wredundant-decls -Wshadow -Wsign-conversion -Wsign-promo -Wstrict-null-sentinel -Wstrict-overflow=5 -Wswitch-default -Wundef -Werror -Wno-unused
Questionable warnings that are present:
I include
-Wno-unused
because I often have variables that I know Iwill use later, but do not yet have the functionality written for.
Removing warnings about that allows me to write in my preferred style
of occasionally deferring the implementation of things. It is useful
to turn that off every once in a while to make sure nothing slipped
through the cracks.
-Wdisabled-optimization
seems like a strong user-preferencesetting. I just added this one to my build (only for optimized builds
for obvious reasons) and it didn't turn anything up, so it doesn't
seem to be an especially chatty warning, at least for the way I code.
I include it (even though code that triggers this warning isn't
necessarily wrong) because I believe in working with my tools instead
of against them. If gcc is telling me that it cannot optimize code
for the way I wrote it, then I should look at rewriting it. I suspect
that code that triggers this warning could benefit from being more
modular, regardless, so although the code is not technically wrong
(probably), stylistically it likely is.
-Wfloat-equal
warns for safe equality comparisons (in particular,comparison with a non-computed value of -1). An example in my code
where I use this is that I have a vector of float. I go through this
vector, and there are some elements I cannot evaluate yet what they
should be, so I set them to -1.0f (since my problem only uses
positive numbers, -1 is out of the domain). I later go through and
update -1.0f values. It does not easily lend itself to a different
method of operation. I suspect that most people don't have this
problem, and comparison of an exact number in floating point is
probably an error, so I'm including it in the default list.
-Wold-style-cast
has a lot of false positives in library code I'm using. In particular, the htonl family of functions used in networking, as well as a Rijndael (AES) encryption implementation I'm using has old-style casts that it warns me about. I intend to replace both of these, but I'm not sure if there is anything else in my code that it will complain about. Most users should probably have this on by default, though.-Wsign-conversion
was a tough one (and almost didn't make thelist). Turning it on in my code generated a huge amount of warnings
(100+). Almost all of them were innocent. However, I have been
careful to use signed integers wherever I wasn't sure, although for
my particular problem domain, I would usually get a slight efficiency
increase using unsigned values due to the large amount of integer
division I do. I sacrificed this efficiency because I was concerned
about accidentally promoting a signed integer to an unsigned and then
dividing (which is not safe, unlike addition, subtraction, and
multiplication). Turning on this warning allowed me to safely change
most of my variables to unsigned types and add a few casts in some
other places. It's currently a little hard to use because the warning
isn't that smart. For instance, if you do
unsigned short + (integral
, that result is implicitly promoted to int. Itconstant expression)
then warns about a potential sign problem if you assign that value to
unsigned
orunsigned short
, even though it's safe. This isdefinitely the most optional warning for almost all users.
-Wsign-promo
: see-Wsign-conversion
.-Wswitch-default
seems pointless (you don't always want a defaultcase if you've enumerated all possibilities explicitly). However,
turning on this warning can enforce something that is probably a good
idea. For cases where you explicitly want to ignore everything except
the listed possibilities (but other numbers are possible), then put
in
default: break;
to make it explicit. If you explicitly enumerateall possibilities, then turning on this warning will help ensure that
you put something like assert (false) to make sure that you've
actually covered all possible options. It lets you be explicit in
what the domain of your problem is and programatically enforces that.
However, you'll have to be careful in just sticking assert (false)
everywhere. It's better than doing nothing with the default case, but
as usual with assert, it won't work in release builds. In other
words, you cannot rely on it to validate numbers that you get from,
say, a network connection or a database that you do not have absolute
control over. Exceptions or returning early are the best way to
handle that (but still require you to have a default case!).
-Werror
is an important one for me. When compiling large amounts ofcode in a multi-threaded build with multiple targets, it's easy for a
warning to slip by. Turning warnings into errors ensures that I
notice them.
Then there is a set of warnings that are not included in the above list because I did not find them to be useful. These are the warnings and my comments on why I'm not including them in the default list:
Warnings that are absent:
-Wabi
is not needed because I'm not combining binaries from different compilers. I tried compiling with it anyway, and it didn't trigger, so it doesn't seem needlessly verbose.-Waggregate-return
is not something that I consider an error. Forinstance, it triggers when using a range-based for loop on a vector
of classes. Return value optimization should take care of any
negative effects of this.
-Wconversion
triggers on this code:short n = 0; n += 2;
Theimplicit conversion to int causes a warning when it's then converted
back to its target type.
-Weffc++
includes a warning if all data members are not initializedin the initializer list. I intentionally do not do this in many
cases, so the set of warnings is too cluttered to be useful. It's
helpful to turn on every once in a while and scan for other warnings,
though (such as non-virtual destructors of base classes). This would
be more useful as a collection of warnings (like
-Wall
) instead ofa single warning on its own.
-Winline
is absent because I don't use the inline keyword foroptimization purposes, just to define functions inline in headers. I
don't care if the optimizer actually inlines it. This warning also
complains if it can't inline a function declared in a class body
(such as an empty virtual destructor).
-Winvalid-pch
is missing because I don't use precompiled headers.-Wmissing-format-attribute
is not used because I do not use gnuextensions. Same for
-Wsuggest-attribute
and several othersPotentially notable for its absence is
-Wno-long-long
, which I haveno need for. I compile with
-std=c++0x
(-std=c++11
in GCC 4.7),which includes
long long
integer types. Those stuck back on C++98 /C++03 may consider adding that exclusion from the warning list.
-Wnormalized=nfc
is already the default option, and looks to be thebest.
-Wpadded
is turned on occasionally to optimize the layout ofclasses, but it is not left on because not all classes have enough
elements to remove padding at the end. In theory I could get some
extra variables for 'free', but it's not worth the extra effort of
maintaining that (if my class size changes, it's not easy to remove
those previously free variables).
-Wstack-protector
is not used because I do not use-fstack-protector
-Wstrict-aliasing=3
is turned on by-Wall
and is the mostaccurate, but it looks like level 1 and 2 give more warnings. In
theory a lower level is a 'stronger' warning, but it's at the cost of
more false positives. My own test code compiled cleanly under all 3
levels.
-Wswitch-enum
isn't behavior that I want. I don't want to handleevery switch statement explicitly. It would be useful if the language
had some mechanism to activate this on specified switch statements
(to ensure that future changes to the enum are handled everywhere
that they need to be), but it's overkill for an "all-or-nothing"
setting.
-Wunsafe-loop-optimizations
causes too many spurious warnings. Itmay be useful to apply this one periodically and manually verify the
results. As an example, it generated this warning in my code when I
looped over all elements in a vector to apply a set of functions to
them (using the range-based for loop). It is also warning for the
constructor of a const array of const std::string (where this is no
loop in user code).
-Wzero-as-null-pointer-constant
and-Wuseless-cast
areGCC-4.7-only warnings, which I will add when I transition to GCC 4.7.
I've filed a few bug reports / enhancement requests at gcc as a result of some of this research, so hopefully I'll be able to eventually add more of the warnings from the "do not include" list to the "include" list. This list includes all warnings mentioned in this thread (plus I think a few extra). Many of the warnings not explicitly mentioned in this post are included as part of another warning I do mention. If anyone notices any warnings that are excluded from this post entirely, let me know.
edit: It looks like I had missed several (which I have now added in). There is actually a second page at http://gcc.gnu.org that is quite well hidden. General warning options and C++ options (scroll down to the bottom for warnings)
天啊,我所有的原始搜索都找到了 99% 的关于如何抑制警告的帖子(足够可怕了),但我刚刚遇到了 此评论,其中有一组可爱的标志(一些不太相关):
交叉检查:
http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
所以,我认为这是一个很好的起点。没有意识到这是一个骗局,但至少它被深深地埋葬了。 :-)
D'oh, all of my original searches turned up 99% of posts on how to suppress warnings (scarily enough), but I just ran across this comment, which has this lovely set of flags (some less relevant):
Cross checked with:
http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
So, I think that's a good starting point. Didn't realize this was a dupe, but at least it was deeply buried. :-)
其中一些已包含在
-Wall
或-Wextra
中。C 的良好基本设置是:
-std=c99 -pedantic -Wall -Wextra -Wwrite-strings -Werror
和 C++
-ansi -pedantic -Wall -Wextra -Weffc++
>(对于 C++ 跳过
-Werror
,因为-Weffc++
有一些烦恼)Some of those are already included in
-Wall
or-Wextra
.A good base setup for C is:
-std=c99 -pedantic -Wall -Wextra -Wwrite-strings -Werror
and for C++
-ansi -pedantic -Wall -Wextra -Weffc++
(skipping
-Werror
for C++ since-Weffc++
has some annoyances)尝试
这是一个快速而肮脏的开始,肯定需要一些调整;一方面,即使您使用适合您语言的名称调用编译器(例如 C++ 的
g++
),您也会收到不适用于该语言的警告(并且编译器将抛出它的手并拒绝继续,直到您删除警告)。另一件事是我在
-Werror
中添加了这一点,因为如果您不修复警告,为什么要关心打开它们呢?您还可以从列表中删除警告。 (例如,我几乎从不在 C++ 中使用-Waggregate-return
。)如果没有其他与性能相关的选项 (
-Wstack-protector
),某些警告将不会执行任何操作。-fdiagnostics-show-option
和 GCC 手册是您的朋友。顺便说一句,有些警告是相互排斥的;特别是使用
-Wtraditional
和-Wold-style-definition
以及-Werror
时,将无法编译。Try
That's a quick and dirty start which will definitely need some tuning; for one thing, even if you call the compiler by the appropriate name for your language (e.g.
g++
for C++), you will get warnings that don't apply to that language (and the compiler will throw up its hands and refuse to continue until you remove the warning).Another thing is that I added in
-Werror
, because if you aren't fixing the warnings, why do you care about turning them on? You can also take warnings out of the list. (For example, I almost never use-Waggregate-return
with C++.)Some warnings won't do anything without other performance related options (
-Wstack-protector
).-fdiagnostics-show-option
and the GCC manual are your friends.By the way, some warnings are mutually exclusive; in particular using
-Wtraditional
and-Wold-style-definition
along with-Werror
, will not compile.