用于启用详尽且详细的g ++警告的标志

问题描述 投票:105回答:5

通常在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 ++预先编译了一组类似的完整警告标志? (我知道其中很多都是一样的。)

c++ g++ warnings
5个回答
119
投票

我经历了一个最小的包含,它应该得到最高级别的警告。然后我从该列表中删除了一组警告,我觉得这些警告实际上并没有表明发生了什么不好的事情,或者在实际构建中使用了太多的误报。我评论为什么我排除的每一个都被排除在外。这是我最后一组建议的警告:

-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

存在可疑警告:

  • 我包括-Wno-unused,因为我经常有变量,我知道我将在以后使用,但还没有为其编写的功能。删除有关它的警告允许我以我喜欢的方式写下偶尔推迟实现的东西。每隔一段时间关闭一次是有用的,以确保没有任何东西从裂缝中滑落。
  • -Wdisabled-optimization似乎是一个强大的用户偏好设置。我刚刚将这一个添加到我的构建中(仅出于显而易见的原因,仅针对优化的构建)并且它没有改变任何东西,所以它似乎不是特别繁琐的警告,至少对于我编码的方式。我包含它(即使触发此警告的代码不一定是错误的)因为我相信使用我的工具而不是反对它们。如果gcc告诉我它不能为我编写它的方式优化代码,那么我应该考虑重写它。我怀疑触发此警告的代码可能会受益于更加模块化,无论如何,所以虽然代码在技术上不是错误的(可能),但风格上可能是这样。
  • -Wfloat-equal警告安全平等比较(特别是与非计算值-1的比较)。在我的代码中我使用它的一个例子是我有一个float向量。我通过这个向量,有一些我无法评估它们应该是什么的元素,所以我将它们设置为-1.0f(因为我的问题只使用正数,-1不在域内)。我稍后通过并更新-1.0f值。它不容易适用于不同的操作方法。我怀疑大多数人都没有这个问题,并且浮点中的确切数字的比较可能是一个错误,所以我将它包含在默认列表中。
  • -Wold-style-cast在我正在使用的库代码中有很多误报。特别是,网络中使用的htonl函数系列以及我正在使用的Rijndael(AES)加密实现具有它向我发出警告的旧式转换。我打算更换这两个,但我不确定我的代码中是否还有其他内容会引起抱怨。但是,大多数用户可能默认启用此功能。
  • -Wsign-conversion是一个艰难的(几乎没有列出名单)。在我的代码中打开它会产生大量的警告(100+)。几乎所有人都是无辜的。但是,在我不确定的地方,我一直小心使用有符号整数,虽然对于我的特定问题域,由于我做了大量的整数除法,我通常会使用无符号值略微提高效率。我牺牲了这种效率,因为我担心意外地将有符号整数提升为无符号然后除法(这不是安全的,不像加法,减法和乘法)。打开此警告允许我安全地将大多数变量更改为无符号类型,并在其他一些位置添加一些强制转换。它目前有点难以使用,因为警告并不那么聪明。例如,如果你执行unsigned short + (integral constant expression),那么结果会被隐式提升为int。然后,如果您将该值分配给unsignedunsigned short,它会发出潜在的符号问题,即使它是安全的。对于几乎所有用户来说,这绝对是最可选的警告。
  • -Wsign-promo:见-Wsign-conversion
  • -Wswitch-default似乎毫无意义(如果你明确列举了所有可能性,你并不总是想要一个默认情况)。但是,打开此警告可以强制执行一些可能是个好主意的事情。对于您明确要忽略除列出的可能性之外的所有内容(但可能有其他数字)的情况,然后输入default: break;以使其显式化。如果您明确列举了所有可能性,那么打开此警告将有助于确保您输入类似assert(false)的内容以确保您实际涵盖了所有可能的选项。它可以让您明确问题的域名并以编程方式强制执行。但是,你必须要小心,只是在任何地方坚持断言(假)。它比默认情况下无所作为更好,但与assert一样,它在发布版本中不起作用。换句话说,您不能依赖它来验证您从网络连接或您无法完全控制的数据库中获得的数字。例外或早退是处理这种情况的最佳方法(但仍需要你有一个默认情况!)。
  • -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 const std :: string的const数组的构造函数(其中这不是用户代码中的循环)。
  • -Wzero-as-null-pointer-constant-Wuseless-cast只是GCC-4.7警告,我将在转换到GCC 4.7时添加。

由于这项研究的结果,我已经在gcc上提交了一些错误报告/增强请求,所以希望我最终能够将“不包含”列表中的更多警告添加到“包含”列表中。此列表包含此主题中提到的所有警告(另外我还要考虑一些额外的警告)。本文中未明确提及的许多警告都包含在我提到的另一个警告的一部分中。如果有人注意到完全被排除在此帖之外的任何警告,请告诉我。

编辑:看起来我错过了几个(我现在添加了)。在http://gcc.gnu.org实际上有一个非常隐蔽的第二页。 General warning optionsC++ options (scroll down to the bottom for warnings)


35
投票

噢,我所有的原始搜索都发布了99%关于如何抑制警告的帖子(非常可靠),但我只是跑过this comment,它有一套可爱的标志(一些不太相关):

交叉检查:

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

所以,我认为这是一个很好的起点。没有意识到这是一个骗局,但至少它被埋没了。 :-)


11
投票

其中一些已经包含在-Wall-Wextra中。

C的良好基础设置是:

-std=c99 -pedantic -Wall -Wextra -Wwrite-strings -Werror

对于C ++

-ansi -pedantic -Wall -Wextra -Weffc++

(跳过-Werror for C ++,因为-Weffc++有一些烦恼)


2
投票

尝试

export CFLAGS="`gcc --help=warnings | grep '\-W' | awk '{print $1 \" \"}' |
sort | uniq` -pedantic -fdiagnostics-show-option -Werror"

这是一个快速而肮脏的开始,肯定需要一些调整;首先,即使您使用适合您的语言的名称调用编译器(例如g++ for C ++),您也会收到不适用于该语言的警告(并且编译器会抛弃它并拒绝继续操作,直到你删除警告)。

另一件事是我加入了-Werror,因为如果你没有修复警告,你为什么要关心它们呢?您也可以从列表中取出警告。 (例如,我几乎从不使用-Waggregate-return和C ++。)

如果没有其他与性能相关的选项(-Wstack-protector),某些警告将无法执行任何操作。 -fdiagnostics-show-option和GCC手册是你的朋友。

顺便说一句,一些警告是相互排斥的;特别是使用-Wtraditional-Wold-style-definition以及-Werror,将无法编译。


0
投票

在我的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)
© www.soinside.com 2019 - 2024. All rights reserved.