关于c ++:启用全面详细的g ++警告的标志

Flags to enable thorough and verbose g++ warnings

我经常在C中的gcc下,从以下警告标志集开始(从多个来源痛苦地组合起来):

1
2
3
4
-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 ++预编译了一组类似的完整警告标志? (我知道其中许多都一样。)


我仔细研究了一下,发现应该包含最高警告级别的最小包含集。然后,我从该列表中删除了一些警告,这些警告我认为实际上并没有表明正在发生不良情况,或者有太多的误报无法在实际版本中使用。我评论了为什么我排除的每个人都被排除在外。这是我最后建议的警告集:

好。

-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进行比较)。我的代码中的一个例子
    我在这里使用的是我有一个浮点向量。我经历了这个
    向量,有些元素我还无法评估
    应该是这样,所以我将它们设置为-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(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可以优化布局
    类,但由于不是所有的类都不够用
    元素以删除最后的填充。理论上我可以得到一些
    " free"的额外变量,但这不值得
    保持这一点(如果我的班级大小发生变化,则不容易删除
    那些以前免费的变量)。

    好。

  • 不使用-Wstack-protector,因为我不使用-fstack-protector

    好。

  • -Wstrict-aliasing=3-Wall打开,是最
    准确,但看起来第1级和第2级发出了更多警告。在
    理论上,较低的级别是"更强"的警告,但这是以牺牲为代价的
    更多误报。我自己的测试代码在所有3种情况下都经过了清晰的编译
    水平。

    好。

  • -Wswitch-enum不是我想要的行为。我不想处理
    每个switch语句都要明确。如果语言是
    有某种机制可以在指定的switch语句上激活它
    (以确保将来对枚举的更改可以在所有地方得到处理
    他们必须是),但对于"全有或全无"而言,这是过分的
    设置。

    好。

  • -Wunsafe-loop-optimizations导致过多的虚假警告。它
    定期应用此代码并手动验证
    结果。例如,当我在代码中生成警告时
    遍历向量中的所有元素以将一组函数应用于
    它们(使用基于范围的for循环)。这也警告
    const std :: string的const数组的构造函数(此处为no
    循环输入用户代码)。

    好。

  • -Wzero-as-null-pointer-constant-Wuseless-cast
    仅适用于GCC-4.7的警告,我将在过渡到GCC 4.7时添加这些警告。

    好。

  • 好。

    由于这项研究,我已在gcc上提交了一些错误报告/增强功能请求,因此希望最终我能够将更多的警告从"不包括"列表添加到"包含"列表中。该列表包括该线程中提到的所有警告(另外,我认为还有一些警告)。我没有提到的另一个警告中包含了本文中未明确提及的许多警告。如果有人发现本帖子完全排除的任何警告,请告诉我。

    好。

    编辑:好像我错过了几个(现在我已经添加了)。实际上,http://gcc.gnu.org上有第二个页面,该页面非常隐蔽。常规警告选项和C ++选项(向下滚动至警告底部)

    好。

    好。


    D'oh,我的所有原始搜索都出现了99%的帖子(关于如何抑制警告)(足够吓人),但我只是碰到了此评论,它带有一组可爱的标志(有些不太相关):

    交叉检查:

    http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    -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

    因此,我认为这是一个很好的起点。没意识到这是一个骗子,但至少它被深深地埋了。 :-)


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

    C的良好基础设置是:

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

    对于C ++

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

    (由于-Weffc++有一些烦恼,因此跳过C ++的-Werror)


    尝试

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

    这是一个快速而肮脏的开始,肯定需要进行一些调整。一方面,即使您使用适合您的语言的名称来调用编译器(例如,对于C ++为g++),您也会收到不适用于该语言的警告(并且编译器会举起手并拒绝继续操作,直到您删除警告为止。

    另一件事是我在-Werror中添加的,因为如果您不修正警告,为什么还要关心将它们打开?您也可以从列表中删除警告。 (例如,我几乎从未在C ++中使用-Waggregate-return。)

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

    顺便说一句,有些警告是互斥的。特别是将-Wtraditional-Wold-style-definition-Werror一起使用时,将无法编译。


    在我的Clion的CmakeLists.txt中

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    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)