标志启用彻底和详细的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
我将构build(至less我的debugging版本)这个警告,并修复我可能可以(通常是一切)的一切,然后只删除标志,如果他们不相关或不可修复(几乎从来没有这样的情况下)。 有时候,如果我不得不在编译的时候离开,那么我还会添加 – -Werror
。
我只是拿起C ++(是的,我比时代落后了15年),而且我想从右脚开始。
我的问题是:是否有人有一个预编译的类似的完整的警告标志为C ++下g++
? (我知道他们中的很多人会是一样的)
我经历了,发现包括应该得到最高级别的警告的最小集合。 然后,我从列表中删除了一组警告,我觉得这些警告实际上并没有指出什么不好的事情发生,否则在实际构build中会有太多的误报。 我评论了为什么我排除的那些被排除在外。 这是我最后一组build议的警告:
-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
因为我经常有variables,我知道我将在以后使用,但还没有写入的function。 删除关于这个问题的警告,可以让我按照自己喜欢的方式写作,偶尔推迟执行。 每隔一段时间closures一次,以确保没有任何东西滑过裂缝是有用的。 -
-Wdisabled-optimization
似乎是一个强大的用户偏好设置。 我只是添加了这个到我的构build(只是为了显而易见的原因优化构build),它没有任何东西,所以它似乎不是一个特别唠叨的警告,至less对于我的代码。 我包括它(即使触发这个警告的代码不一定是错误的),因为我相信与我的工具,而不是对他们的工作。 如果gcc告诉我,它不能为我写的方式优化代码,那么我应该考虑重写它。 我怀疑触发这个警告的代码可以从更模块化中受益,不pipe怎样,尽pipe代码在技术上不是错误的(可能),但是在风格上它可能是错误的。 -
-Wfloat-equal
警告安全的相等比较(特别是,与非计算值-1进行比较)。 我使用这个代码的一个例子是我有一个float的向量。 我经历了这个向量,还有一些元素我不能评估它们应该是什么,所以我把它们设置为-1.0f(因为我的问题只使用正数,-1不在域中)。 我后来通过并更新-1.0f值。 它不容易适应不同的操作方法。 我怀疑大多数人没有这个问题,并且在浮点数中比较确切的数字可能是一个错误,所以我将它包含在默认列表中。 -
-Wold-style-cast
在我使用的库代码中有很多误报。 特别是,networking中使用的htonlfunction家族,以及我使用的Rijndael(AES)encryption实现都具有老式的演员阵容,它提醒我。 我打算取代这两个,但我不知道是否有任何其他的代码,它会抱怨。 不过,大多数用户应该可以默认使用这个function。 -
-Wsign-conversion
是一个艰难的(几乎没有列出)。 在我的代码中打开它会产生大量的警告(100+)。 几乎所有的人都是无辜的。 但是,在我不确定的地方,我一直很小心地使用有符号整数,但是对于我特殊的问题领域,由于大量的整数除法,我通常会使用无符号值来略微提高效率。 我牺牲了这个效率,因为我担心无意中将一个有符号整数提升为无符号,然后进行分割(这与加法,减法和乘法不一样是不安全的)。 打开这个警告允许我安全地将大部分variables转换为无符号types,并在其他一些地方添加一些转换。 目前有点难以使用,因为警告不是那么聪明。 例如,如果你做unsigned short + (integral constant expression)
,那么这个结果会隐含地提升为int。 然后,如果将该值分配给unsigned
或unsigned short
unsigned
,则会警告潜在的符号问题,即使它是安全的。 这绝对是几乎所有用户最可选的警告。 -
-Wsign-promo
:请参阅-Wsign-conversion
。 -
-Wswitch-default
似乎毫无意义(如果你明确列举了所有的可能性,你并不总是需要一个默认情况)。 但是,打开这个警告可以强制执行一些可能是个好主意的方法。 对于除了列出的可能性(但其他数字都可能)之外明确地要忽略所有default: break;
,则default: break;
使其明确。 如果您明确列举了所有可能性,那么打开此警告将有助于确保您放置类似assert(false)的内容,以确保您已经覆盖了所有可能的选项。 它可以让你明确你的问题的领域是什么,并以编程方式强制执行。 但是,你必须小心,坚持断言(错误)到处都是。 这比默认情况下没有做什么好,但像往常一样,在发布版本中不起作用。 换句话说,你不能依靠它来validation你得到的数字,比如networking连接或者你没有绝对控制的数据库。 例外情况或提早回来是处理这种情况的最好方法(但仍然要求您有一个默认情况!)。 -
-Werror
对我来说,-Werror
是重要的。 在多目标multithreading构build中编译大量代码时,很容易出现警告。 将警告转化为错误可以确保我注意到它们。
然后有一组警告没有包含在上面的列表中,因为我没有发现它们是有用的。 这些警告和我的意见,为什么我不包括他们在默认列表中:
警告是缺席的:
-
-Wabi
是不需要的,因为我没有组合来自不同编译器的二进制文件。 无论如何,我试着编译它,并没有触发,所以它似乎不必要的冗长。 -
-Waggregate-return
不是我认为是错误的东西。 例如,它在类的向量上使用基于范围的for循环时触发。 返回值优化应该考虑到这个的任何负面影响。 -
此代码上的
-Wconversion
触发器:short n = 0; n += 2;
short n = 0; n += 2;
隐式转换为int时,会将其转换回目标types。 -
如果在初始化程序列表中没有初始化所有数据成员,则
-Weffc++
包含警告。 我故意在很多情况下不这样做,所以这套警告太混乱了,没用。 尽pipe每隔一段时间打开一次并扫描其他警告(例如基类的非虚拟析构函数)是很有帮助的。 这将作为警告(如-Wall
)的集合而不是单独的警告的集合。 -
-Winline
不存在,因为我没有使用inline关键字进行优化,只是为了在头文件中定义函数。 我不在乎优化器是否真的将其内联。 这个警告也会抱怨,如果它不能内联在一个类正文中声明的函数(如空的虚拟析构函数)。 -
-Winvalid-pch
缺less,因为我不使用预编译头。 -
-Wmissing-format-attribute
不使用,因为我不使用GNU扩展。 同样的-Wsuggest-attribute
和其他几个 -
可能值得注意的是,这是我没有必要的。 我使用
-std=c++0x
(在GCC 4.7中为-std=c++11
进行编译,其中包括long long
整数types。 那些停滞在C ++ 98 / C ++ 03上的人可能会考虑从警告列表中添加这个排除。 -
-Wnormalized=nfc
已经是默认选项,并且看起来是最好的。 -
-Wpadded
偶尔会打开,以优化类的布局,但是不会留下,因为并不是所有的类都有足够的元素来删除填充。 从理论上讲,我可以为“自由”获得一些额外的variables,但不值得花费额外的努力(如果我的课堂大小发生变化,去除那些以前的自由variables并不容易)。 -
-Wstack-protector
没有使用-Wstack-protector
因为我不使用-fstack-protector
-
-Wstrict-aliasing=3
被-Wall
打开,并且是最准确的,但是看起来像级别1和级别2给出了更多的警告。 从理论上讲,较低的水平是一个“更强”的警告,但这是以更多的误报为代价的。 我自己的testing代码在所有3个层次上都干净地编译。 -
-Wswitch-enum
不是我想要的行为。 我不想明确处理每个switch语句。 如果语言在指定的switch语句中有一些机制来激活这个语句(以确保将来对enum进行的更改能够在所需的任何地方进行处理),那么这将是有用的,但对于“全有或全无”设置来说,这是过度的。 -
-Wunsafe-loop-optimizations
会导致太多的虚假警告。 定期应用这个工具并手动validation结果可能是有用的。 作为一个例子,它在我的代码中生成了这个警告,当我遍历一个向量中的所有元素,以便向它们应用一组函数时(使用基于范围的for循环)。 它也是const const std :: string(在用户代码中没有循环)的const数组的构造函数的警告。 -
-Wzero-as-null-pointer-constant
和-Wuseless-cast
是GCC-4.7-only警告,我将在转换到GCC 4.7时添加。
我已经在gcc提交了一些bug报告/增强请求,所以希望我能够最终将更多的警告从“不包含”列表添加到“包含”列表中。 这个列表包括在这个线程中提到的所有警告(加上我想一些额外的)。 这篇文章中没有明确提到的许多警告都包含在我提到的另一个警告中。 如果有人注意到这个post中排除的任何警告,请告诉我。
编辑:它看起来像我已经错过了几个(我现在已经join)。 实际上在http://gcc.gnu.org有第二个页面,隐藏的很好。; 常规警告选项和C ++选项(向下滚动到警告)
噢,我所有的原始search都发布了99%的关于如何抑制警告(足够可怕)的post,但我只是碰到了这个评论 , 这个评论有一些可爱的标志:
交叉检查:
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
所以,我认为这是一个很好的起点。 没有意识到这是一个骗局,但至less它被深埋。 🙂
其中一些已经包含在-Wall
或-Wextra
。
C的一个好的基础设置是:
-std=c99 -pedantic -Wall -Wextra -Wwrite-strings -Werror
和C ++
-ansi -pedantic -Wall -Wextra -Weffc++
(跳过 – -Werror
的C ++,因为-Weffc++
有一些烦恼)
尝试
export CFLAGS="`gcc --help=warnings | grep '\-W' | awk '{print $1 \" \"}' | sort | uniq` -pedantic -fdiagnostic-show-option -Werror"
这是一个快速和肮脏的开始,这肯定会需要一些调整; 一方面,即使你用适合你的语言的名字来调用编译器(例如,用于C ++的g ++),你也会得到不适用于该语言的警告(编译器会举起手来拒绝继续直到你删除警告)。
另一件事是,我join了 – 错误的,因为如果你没有解决警告,你为什么关心打开它? 您也可以从列表中取出警告(例如,我几乎从不使用-Waggregate-return
C ++ -Waggregate-return
)。
如果没有其他性能相关的选项,一些警告将不会做任何事情( -Wstack-protector
)。 -fdiagnostic-show-option
和GCC手册是你的朋友。
顺便说一下,一些警告是相互排斥的; 特别是使用-Wtraditional
和-Wold-style-definition
-Werror
,不会编译。