C++ 启用彻底和详细的 g++ 警告的标志
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5088460/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Flags to enable thorough and verbose g++ warnings
提问by Sdaz MacSkibbons
Often in C under gcc
, I will start with the following set of warning flags (painfully assembled from multiple sources):
通常在 C 下gcc
,我将从以下一组警告标志开始(从多个来源痛苦地组装):
-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.
我将使用这组警告构建(至少是我的调试版本)并修复我可能会做的所有事情(通常是所有事情),然后仅删除不相关或不可修复的标志(几乎从来没有)。有时,-Werror
如果我在编译时必须离开,我也会补充。
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.
我刚开始学习 C++(是的,我落后于时代 15 年),我想从正确的角度开始。
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.)
我的问题是:是否有人在g++
. (我知道他们中的许多人都是一样的。)
采纳答案by Sdaz MacSkibbons
D'oh, all of my original searches turned up 99% of posts on how to suppresswarnings (scarily enough), but I just ran across this comment, which has this lovely set of flags (some less relevant):
天啊,我所有的原始搜索都出现了 99% 的关于如何抑制警告的帖子(足够可怕),但我刚看到这个评论,它有一组可爱的标志(一些不太相关):
Cross checked with:
交叉检查:
http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
-g -O -Wall -Weffc++ -pedantic \
-pedantic-errors -Wextra -Waggregate-return -Wcast-align \
-Wcast-qual -Wconversion \
-Wdisabled-optimization \
-Werror -Wfloat-equal -Wformat=2 \
-Wformat-nonliteral -Wformat-security \
-Wformat-y2k \
-Wimplicit -Wimport -Winit-self -Winline \
-Winvalid-pch \
-Wlong-long \
-Wmissing-field-initializers -Wmissing-format-attribute \
-Wmissing-include-dirs -Wmissing-noreturn \
-Wpacked -Wpadded -Wpointer-arith \
-Wredundant-decls \
-Wshadow -Wstack-protector \
-Wstrict-aliasing=2 -Wswitch-default \
-Wswitch-enum \
-Wunreachable-code -Wunused \
-Wunused-parameter \
-Wvariadic-macros \
-Wwrite-strings
So, I think that's a good starting point. Didn't realize this was a dupe, but at least it was deeply buried. :-)
所以,我认为这是一个很好的起点。没有意识到这是一个骗局,但至少它被深深地掩埋了。:-)
回答by David Stone
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
-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 I will 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-preference setting. 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 the list). 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 dounsigned short + (integral constant expression)
, that result is implicitly promoted to int. It then warns about a potential sign problem if you assign that value tounsigned
orunsigned short
, even though it's safe. This is definitely the most optional warning for almost all users.-Wsign-promo
: see-Wsign-conversion
.-Wswitch-default
seems pointless (you don't always want a default case 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 indefault: break;
to make it explicit. If you explicitly enumerate all 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 of code 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.
我包括在内
-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 constant expression)
,该结果被隐式提升为 int。然后,如果您将该值分配给unsigned
或unsigned short
,即使它是安全的,它也会警告潜在的符号问题 。对于几乎所有用户来说,这绝对是最可选的警告。-Wsign-promo
: 见-Wsign-conversion
。-Wswitch-default
似乎毫无意义(如果您已经明确列举了所有可能性,您并不总是想要默认情况)。但是,打开此警告可以强制执行一些可能是个好主意的事情。对于您明确希望忽略除列出的可能性之外的所有内容(但其他数字也是可能的)的情况,然后输入default: break;
使其明确。如果您明确列举了所有可能性,那么打开此警告将有助于确保您输入诸如 assert (false) 之类的内容,以确保您实际上涵盖了所有可能的选项。它让您明确问题的领域是什么,并以编程方式强制执行。但是,您必须小心地将 assert (false) 粘贴到任何地方。这比在默认情况下什么都不做要好,但与断言一样,它在发布版本中不起作用。换句话说,您不能依靠它来验证您从网络连接或您无法绝对控制的数据库中获得的数字。异常或提前返回是最好的处理方式(但仍然需要你有一个默认情况!)。-Werror
对我来说很重要。在具有多个目标的多线程构建中编译大量代码时,很容易忽略警告。将警告转化为错误可确保我注意到它们。
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. For instance, 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;
The implicit 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 initialized in 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 of a single warning on its own.-Winline
is absent because I don't use the inline keyword for optimization 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 gnu extensions. Same for-Wsuggest-attribute
and several othersPotentially notable for its absence is
-Wno-long-long
, which I have no need for. I compile with-std=c++0x
(-std=c++11
in GCC 4.7), which includeslong 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 the best.-Wpadded
is turned on occasionally to optimize the layout of classes, 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 most accurate, 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 handle every 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. It may 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
are GCC-4.7-only warnings, which I will add when I transition to GCC 4.7.
-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
(-std=c++11
在 GCC 4.7 中)编译,其中包括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 数组的构造函数的警告(其中这不是用户代码中的循环)。-Wzero-as-null-pointer-constant
并且-Wuseless-cast
是仅限 GCC-4.7 的警告,我将在过渡到 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.
作为这项研究的结果,我在 gcc 提交了一些错误报告/增强请求,所以希望我最终能够将更多来自“不包括”列表的警告添加到“包含”列表. 此列表包括此线程中提到的所有警告(加上我认为的一些额外警告)。这篇文章中没有明确提到的许多警告都包含在我提到的另一个警告中。如果有人注意到这篇文章中完全排除的任何警告,请告诉我。
edit:It looks like I had missed several (which I have now added in). There is actually a second page at http://gcc.gnu.orgthat is quite well hidden. General warning optionsand C++ options (scroll down to the bottom for warnings)
编辑:看起来我错过了几个(我现在已经添加了)。实际上在http://gcc.gnu.org上还有第二页隐藏得很好。一般警告选项和C++ 选项(向下滚动到底部的警告)
回答by ?imon Tóth
Some of those are already included in -Wall
or -Wextra
.
其中一些已包含在-Wall
或 中-Wextra
。
A good base setup for C is:
C 的良好基础设置是:
-std=c99 -pedantic -Wall -Wextra -Wwrite-strings -Werror
-std=c99 -pedantic -Wall -Wextra -Wwrite-strings -Werror
and for C++
和 C++
-ansi -pedantic -Wall -Wextra -Weffc++
-ansi -pedantic -Wall -Wextra -Weffc++
(skipping -Werror
for C++ since -Weffc++
has some annoyances)
(跳过-Werror
C++ 因为-Weffc++
有一些烦恼)
回答by Nathan Paul Simons
Try
尝试
export CFLAGS="`gcc --help=warnings | grep '\-W' | awk '{print \" \"}' |
sort | uniq` -pedantic -fdiagnostics-show-option -Werror"
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).
这是一个快速而肮脏的开始,肯定需要一些调整;一方面,即使您使用适合您语言的名称(例如g++
C++)调用编译器,您也会收到不适用于该语言的警告(并且编译器会举手拒绝继续,直到您删除警告)。
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++.)
另一件事是我添加了-Werror
,因为如果你不修复警告,你为什么关心打开它们?您还可以从列表中删除警告。(例如,我几乎从不使用-Waggregate-return
C++。)
Some warnings won't do anything without other performance related options (-Wstack-protector
). -fdiagnostics-show-option
and the GCC manual are your friends.
如果没有其他与性能相关的选项 ( -Wstack-protector
),某些警告将无济于事。-fdiagnostics-show-option
和 GCC 手册是您的朋友。
By the way, some warnings are mutually exclusive; in particular using -Wtraditional
and -Wold-style-definition
along with -Werror
, will not compile.
顺便说一下,有些警告是相互排斥的;特别是使用-Wtraditional
和-Wold-style-definition
一起-Werror
,将无法编译。
回答by snr
In my Clion's CmakeLists.txt
在我的 Clion 的 CmakeLists.txt 中
cmake_minimum_required(VERSION 3.13)
project(cpp17)
set(CMAKE_CXX_STANDARD 17)
set(GCC_COVERAGE_COMPILE_FLAGS "-std=c++17 -Wall -Weffc++ -Wno-error=effc++ -pedantic \
-Weverything -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-newline-eof \
-pedantic-errors -Wextra -Waggregate-return -Wcast-align \
-Wcast-qual -Wconversion \
-Wdisabled-optimization \
-Werror -Wfloat-equal -Wformat=2 \
-Wformat-nonliteral -Wformat-security \
-Wformat-y2k \
-Wimplicit -Wimport -Winit-self -Winline -Winvalid-pch \
-Wlong-long \
-Wmissing-field-initializers -Wmissing-format-attribute \
-Wmissing-include-dirs -Wmissing-noreturn \
-Wpacked -Wpadded -Wpointer-arith \
-Wredundant-decls \
-Wshadow -Wstack-protector \
-Wstrict-aliasing=2 -Wswitch-default \
-Wswitch-enum \
-Wunreachable-code -Wunused \
-Wunused-parameter \
-Wvariadic-macros \
-Wwrite-strings")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GCC_COVERAGE_COMPILE_FLAGS}" )
add_executable(cpp17 main.cpp)