2025年gcc警告选项汇总

gcc警告选项汇总参考资料 https gcc gnu org onlinedocs gcc Optimize Options html Optimize Options 请求或取消警告的选项 警告是诊断消息 报告的结构本质上不是错误的 但是有风险或表明可能有错误 以下与语言无关的选项不会启用特定的警告 但会控制 GCC 生成的诊断类型

大家好,我是讯享网,很高兴认识大家。

参考资料:https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html#Optimize-Options

请求或取消警告的选项

警告是诊断消息,报告的结构本质上不是错误的,但是有风险或表明可能有错误。

以下与语言无关的选项不会启用特定的警告,但会控制GCC生成的诊断类型。
-fsyntax-only
检查代码中的语法错误,但除此之外不要做任何事情。

每个可控警告的警告消息都包含控制警告的选项。 那么该选项可以与-Werror =和-Wno-error =一起使用 ,如上所述。 (可以使用-fno-diagnostics-show-option标志禁用警告消息中的选项打印。)

请注意,指定-Werror = foo会自动隐含-W foo 。 但是, -Wno-error = foo并不意味着什么。

例如,您可以使用以“ -W ”开头的选项来请求许多特定的警告 - 可以隐式地请求隐式声明的警告。 这些特定警告选项中的每一个都有一个以“ -Wno- ”开始的否定形式来关闭警告; 例如, -Wno-implicit 。 本手册仅列出两种形式中的一种,无论哪种都不是默认值。 有关其他语言特定的选项,还可以参考C ++ Dialect Options和Objective-C以及Objective-C ++ Dialect Options 。

某些选项(如-Wall和-Wextra )会打开其他选项,例如-Wunused ,这可能会启用其他选项,例如-Wunused-value 。 正面和负面形式的综合作用是,更具体的选项优先于不特定的选项,与命令行中的位置无关。 对于相同特征的选项,最后一个生效。 通过编译指示启用或禁用的选项(请参阅诊断编译指示 )将起作用,就好像它们出现在命令行末尾一样。

当请求无法识别的警告选项时(例如-Wunknown-warning ),GCC将发出诊断,指出该选项未被识别。 但是,如果使用-Wno- form,行为会稍有不同:除非正在生成其他诊断,否则不会生成-Wno-unknown-warning诊断。 这允许在旧编译器中使用新的-Wno-选项,但如果出现问题,编译器会警告存在无法识别的选项。

-Wpedantic
-pedantic
发布严格的ISO C和ISO C ++所要求的所有警告; 拒绝所有使用禁止扩展的程序,以及其他一些不遵循ISO C和ISO C ++的程序。 对于ISO C,遵循由所使用的任何-std选项指定的ISO C标准版本。

有效的ISO C和ISO C ++程序应该在有或没有这个选项的情况下正确编译(尽管极少数需要指定所需版本的ISO C的-ansi或-std选项)。 但是,如果没有这个选项,也支持某些GNU扩展和传统的C和C ++特性。 有了这个选项,他们被拒绝。

-Wpedantic不会导致使用名称以“ __ ”开头和结尾的替代关键字的警告消息。 在__extension__之后的表达式中也禁止了迂腐警告。 但是,只有系统头文件应该使用这些转义路由; 应用程序应该避免它们。 请参阅备用关键字 。

一些用户尝试使用-Wantantic来检查程序是否符合严格的ISO C标准。 他们很快就发现它并没有达到他们想要的水平:它找到了一些非ISO的做法,但不是所有的只有ISO C 需要诊断的那些做法,以及其他一些诊断已经添加了的做法。

报告任何不符合ISO C标准的功能在某些情况下可能会有用,但需要大量额外的工作,并且与-Wantantic完全不同。 我们不打算在不久的将来支持这种功能。

如果用-std指定的标准表示C的GNU扩展方言,如’ gnu90 ‘或’ gnu99 ',则存在相应的基本标准 ,GNU扩展方言所基于的ISO C版本。 -Wpedantic给出的警告在基本标准要求的地方给出。 (这种警告只适用于不在指定的GNU C方言中的功能是没有意义的,因为根据定义,C的GNU方言包括编译器支持的所有功能,并且没有任何可警告的内容。)

-打开以下警告标志:

-Waddress -Warray-bounds=1 (only with -O2) -Wbool-compare -Wbool-operation -Wc++11-compat -Wc++14-compat -Wcatch-value (C++ and Objective-C++ only) -Wchar-subscripts -Wcomment -Wduplicate-decl-specifier (C and Objective-C only) -Wenum-compare (in C/ObjC; this is on by default in C++) -Wformat -Wint-in-bool-context -Wimplicit (C and Objective-C only) -Wimplicit-int (C and Objective-C only) -Wimplicit-function-declaration (C and Objective-C only) -Winit-self (only for C++) -Wlogical-not-parentheses -Wmain (only for C/ObjC and unless -ffreestanding) -Wmaybe-uninitialized -Wmemset-elt-size -Wmemset-transposed-args -Wmisleading-indentation (only for C/C++) -Wmissing-attributes -Wmissing-braces (only for C/ObjC) -Wmultistatement-macros -Wnarrowing (only for C++) -Wnonnull -Wnonnull-compare -Wopenmp-simd -Wparentheses -Wpointer-sign -Wreorder -Wrestrict -Wreturn-type -Wsequence-point -Wsign-compare (only in C++) -Wsizeof-pointer-div -Wsizeof-pointer-memaccess -Wstrict-aliasing -Wstrict-overflow=1 -Wswitch -Wtautological-compare -Wtrigraphs -Wuninitialized -Wunknown-pragmas -Wunused-function -Wunused-label -Wunused-value -Wunused-variable -Wvolatile-register-var 

讯享网

请注意,一些警告标志并不是由-Wall隐含的。 其中一些人警告用户通常不认为有问题的建筑,但有时候您可能希望检查; 其他人警告在某些情况下必要或难以避免的构造,并且没有简单的方法来修改代码来抑制警告。 其中一些由-Wextra启用,但其中许多必须单独启用。

讯享网-Wclobbered -Wcast-function-type -Wempty-body -Wignored-qualifiers -Wimplicit-fallthrough=3 -Wmissing-field-initializers -Wmissing-parameter-type (C only) -Wold-style-declaration (C only) -Woverride-init -Wsign-compare (C only) -Wtype-limits -Wuninitialized -Wshift-negative-value (in C++03 and in C99 and newer) -Wunused-parameter (only with -Wunused or -Wall) -Wunused-but-set-parameter (only with -Wunused or -Wall) 

选项-Wextra还会打印以下情况的警告消息:

指针与整数零与< , <= , >或>= 。
(仅限C ++)枚举器和非枚举器都出现在条件表达式中。
(仅限C ++)不明确的虚拟基础。
(仅限C ++)为已声明为register的数组下标。
(仅限C ++)取得已声明register的变量的地址。
(仅限C ++)基类不在派生类的复制构造函数中初始化。
-Wchar-subscripts
警告如果数组下标有char类型。 这是错误的常见原因,因为程序员经常忘记这种类型是在某些机器上签名的。 此警告由-Wall启用。

禁止#warning指令发出的警告消息。

使用double意外执行计算很容易,因为浮点文字隐含了double类型。 例如,在:

float area(float radius) { return 3.14159 * radius * radius; } 

编译器使用double执行整个计算,因为浮点文字是double 。

-Wformat
-Wformat= n
检查对printf和scanf等的调用,以确保提供的参数的类型与指定的格式字符串相匹配,并且格式字符串中指定的转换有意义。 这包括标准函数,以及其他由printf , scanf , strftime和strfmon (X / Open扩展,而不是C标准)系列(或其他特定于目标系列)的格式属性(请参阅函数属性 )指定的标准函数。 哪些函数在没有指定格式属性的情况下被检查取决于所选择的标准版本,并且没有指定属性的函数的这些检查由-freestanding或-fno-builtin禁用。

格式将根据GNU libc版本2.2支持的格式特性进行检查。 这些包括所有ISO C90和C99功能,以及Single Unix Specification和一些BSD和GNU扩展的功能。 其他库实现可能不支持所有这些功能; GCC不支持关于超出特定图书馆限制的功能的警告。 但是,如果-Wpedantic与-Wformat 一起使用,则会提供有关格式特征的警告,但不包括在选定的标准版本中(但不包含strfmon格式,因为这些格式不在C标准的任何版本中)。 请参阅控制C语言的选项 。

-Wformat=1
-Wformat
选项-Wformat相当于-Wformat = 1 , -Wno-format相当于-Wformat = 0 。 由于-Wformat还检查几个函数的空格式参数, -Wformat也意味着-Wnonnull 。 这种格式检查级别的某些方面可以通过以下选项禁用: -Wno-format-contains-nul , -Wno-format-extra-args和-Wno-format-zero-length 。 -Wformat由-Wall启用。

如果未使用的参数位于用’ $ '操作数编号规范指定的已使用参数之间,通常仍会给出警告,因为实现无法知道传递给va_arg类型以跳过未使用的参数。 但是,在scanf格式的情况下,如果未使用的参数全部是指针,则此选项会抑制警告,因为Single Unix Specification指出允许使用这些未使用的参数。

-Wformat-overflow
-Wformat-overflow= level
警告对可能溢出目标缓冲区的格式化输入/输出函数(如sprintf和vsprintf 。 当由格式指令写入的确切字节数在编译时无法确定时,它将根据启发式进行估计,这取决于级别参数和优化。 虽然启用优化在大多数情况下会提高警告的准确性,但也可能导致误报。

-Wformat-overflow
-Wformat-overflow=1
-Wformat启用的-Wformat-overflow的第1级采用了一种保守的方法,只警告最有可能溢出缓冲区的调用。 在此级别,格式化具有未知值的指令的数字参数假定值为1,未知长度的字符串为空。 已知绑定到其类型的子范围的数字参数,或者其输出受其指令的精度或有限的字符串文字限制的字符串参数被假定为取值范围内的值,该范围导致输出中的大部分字节。 例如,下面对sprintf的调用被诊断出来,因为即使a和b都等于零,函数附加到目标缓冲区的终止NUL字符( ‘\0’ )也将被写入其末尾。 将缓冲区的大小增加一个字节足以避免警告,尽管它可能不足以避免溢出。

讯享网void f(int a,int b) { char buf [13]; sprintf(buf,“a =%i,b =%i \ n”,a,b); } 

在第2级,上述示例中的调用再次被诊断,但是这次因为使用等于32位的INT_MIN ,第一个%i指令将在目标缓冲区的末尾写入其一些数字。 为了保证呼叫安全,无论两个变量的值如何,目标缓冲区的大小必须增加到至少34个字节。 GCC在警告后的信息说明中包含缓冲区的最小大小。

增加目标缓冲区大小的替代方法是限制格式化值的范围。 字符串参数的最大长度可以通过指定格式指令中的精度来限制。 当格式指令的数值参数可以假定为小于它们类型的精度时,为格式说明符选择适当的长度修饰符将减少所需的缓冲区大小。 例如,如果上面示例中的a和b可以假定为处于short int类型的精度范围内,那么使用%hi格式指令或将参数强制转换为short可将缓冲区的最大所需大小减少到24个字节。

 void f(int a,int b) { char buf [23]; sprintf(buf,“a =%hi,b =%i \ n”,a,(简写)b); } 

-Wformat-truncation
-Wformat-truncation= level
警告关于调用可能导致输出截断的格式化输入/输出函数(如snprintf和vsnprintf警告。 当由格式指令写入的确切字节数在编译时无法确定时,它将根据启发式进行估计,这取决于级别参数和优化。 虽然启用优化在大多数情况下会提高警告的准确性,但也可能导致误报。 除非另有说明,该选项使用相同的逻辑 - 格式溢出 。

-Wformat-truncation
-Wformat-truncation=1
-Wformat启用的-Wformat-truncation的 Level 1采用了一种保守的方法,只警告对有界函数的调用,该函数的返回值未使用,并且很可能导致输出截断。

-Wnonnull包含在-Wall和-Wformat中 。 它可以通过-Wno-nonnull选项禁用。

-Wnonnull-compare包含在-Wall中 。 它可以通过-Wno-nonnull-compare选项禁用。

例如,只有在指定-Winit-self时,GCC才会在下面的代码片段中提醒i未初始化:

讯享网 int f() { int i = i; 回报我; } 

此警告由C ++中的-Wall启用。

switch (cond) { case 1: a = 1; break; case 2: a = 2; case 3: a = 3; break; } 

当警告的最后一个语句不能通过时,例如当有一个返回语句或对noreturn属性声明的函数调用时,此警告不会警告。 -Wimplicit-fallthrough =也考虑到了控制流程语句,比如ifs,并且只在适当的时候发出警告。 例如

讯享网switch (cond) { case 1: if (i > 3) { bar (5); break; } else if (i < 1) { bar (0); } else return; default: … } 

由于在某些情况下可能会出现切换情况,GCC提供了一个属性__attribute__ ((fallthrough)) ,该属性将与空语句一起使用来抑制通常会发生的警告:

switch (cond) { case 1: bar (0); __attribute__ ((fallthrough)); default: … } 

C ++ 17提供了一种标准的方法来抑制使用[[fallthrough]];的-Wimplicit-Fallthrough警告[[fallthrough]]; 而不是GNU属性。 在C ++ 11或C ++ 14中,用户可以使用[[gnu::fallthrough]]; ,这是一个GNU扩展。 除了这些属性外,还可以添加一条跌落评论以使警告消失。 C或C ++样式注释的整个主体应该与下面列出的给定正则表达式匹配。 选项参数n指定接受哪种注释:

-Wimplicit-Fallthrough = 0完全禁用警告。
-Wimplicit-fallthrough = 1匹配.正则表达式,任何评论都被用作fallthrough评论。
-wimplicit-fallthrough = 2 case nonnsitively matches .falls?[ \t-]thr(ough|u).正则表达式。
-Wimplicit-fallthrough = 3大小写敏感地匹配以下正则表达式之一:
-fallthrough
@fallthrough@
lint -fallthrough[ \t]

[ \t.!]
(ELSE,? |INTENTIONAL(LY)? )?
FALL(S | |-)?THR(OUGH|U)[ \t.!]
(-[^\n\r]
)?
[ \t.!](Else,? |Intentional(ly)? )?
Fall((s | |-)[Tt]|t)hr(ough|u)[ \t.!]
(-[^\n\r])?
[ \t.!]
([Ee]lse,? |[Ii]ntentional(ly)? )?
fall(s | |-)?thr(ough|u)[ \t.!](-[^\n\r])?
-Wimplicit-fallthrough = 4大小写敏感地匹配以下正则表达式之一:
-fallthrough
@fallthrough@
lint -fallthrough[ \t]*
[ \t]FALLTHR(OUGH|U)[ \t]
-Wimplicit-Fallthrough = 5不会将任何注释识别为传递注释,只有属性禁用警告。
注释需要在可选空白和其他注释之后遵循case或default关键字或者某个case或default标签之前的用户标签。

讯享网switch (cond) { case 1: bar (0); /* FALLTHRU */ default: … } 

-Wimplicit-Fallthrough = 3警告由-Wextra启用。

此警告也由-Wextra启用。

在下面的例子中,对“bar”的调用被误导地缩进,就好像它受到“if”条件的保护。

 if(some_condition()) foo(); bar(); /* Gotcha: this is not guarded by the "if". */ 

在混合制表符和空格的情况下,警告使用-ftabstop =选项来确定语句是否排队(默认为8)。

对于涉及多行预处理器逻辑的代码(如以下示例),不会发出该警告。

讯享网 if (flagA) foo (0); #if SOME_CONDITION_THAT_DOES_NOT_HOLD if (flagB) #endif foo (1); 

该警告不会在#line指令之后发出,因为这通常会指示自动生成的代码,并且不会假定该指令所引用的文件的布局。

此警告是由C和C ++中的-Wall启用的。

-Wmissing-attributes由-Wall启用。

例如,由于下面的主要函数模板的声明使用属性malloc和alloc_size ,因此模板的显式特化的声明被诊断,因为它缺少其中一个属性。

template <class T> T* __attribute__ ((malloc, alloc_size (1))) allocate (size_t); template <> void* __attribute__ ((malloc)) // missing alloc_size allocate<void> (size_t); 
讯享网 int a [2] [2] = {0,1,2,3}; int b [2] [2] = { 
  
    
  {0,1},{2,3}}; 

此警告由-Wall启用。

例如:

#define DOIT x++; y++ if (c) DOIT; 

将无条件地增加y ,而不仅仅是当c成立时。 通常可以通过将宏包装在do-while循环中来解决该问题:

讯享网#define DOIT do { x++; y++; } while (0) if (c) DOIT; 

此警告是由C和C ++中的-Wall启用的。

还会发出如x<=y<=z等比较结果的警告。 这相当于(x<=y ? 1 : 0) <= z ,这是与普通数学符号的解释不同的解释。

还警告GNU扩展的危险用途?:省略中间操作数。 当条件在? :运算符是一个布尔表达式,省略的值始终为1.程序员通常希望它是在条件表达式内计算的值。

对于C ++,这也会在声明中警告一些不必要的括号,这可能表示试图在函数调用而不是声明:

{ // Declares a local variable called mymutex. std::unique_lock<std::mutex> (mymutex); // User meant std::unique_lock<std::mutex> lock (mymutex); } 

此警告由-Wall启用。

C和C ++标准定义了C / C ++程序中的表达式按顺序点进行评估的顺序 , 顺序点表示执行程序各部分之间的部分顺序:在顺序点之前执行的顺序点和在执行之后执行的顺序点它。 这些发生在对一个&& , ||的第一个操作数进行评估之后,对一个完整表达式(不是更大表达式的一部分)进行评估之后。 , ? : ? :或(逗号)运算符,然后调用一个函数(但在其参数和表达被调用函数的表达式之后)以及某些其他地方。 除了顺序点规则所表达的内容之外,没有指定表达式的子表达式的评估顺序。 所有这些规则只描述部分顺序而不是全部顺序,例如,如果在一个表达式中调用了两个函数,而它们之间没有顺序点,则函数被调用的顺序未被指定。 但是,标准委员会已经裁定函数调用不重叠。

在序列点之间不会指定对对象值的修改生效。 行为依赖于此的程序具有未定义的行为; C和C ++标准规定:“在前一个和下一个序列点之间,一个对象最多应该通过评估一个表达式修改其存储值。 此外,先前值只能读取,以确定要存储的值。“ 如果一个程序违反了这些规则,任何特定实现的结果都是完全不可预测的。

具有未定义行为的代码示例是a = a++; , a[n] = b[n++]和a[i++] = i; 。 一些更复杂的病例不会被这个选项诊断出来,它可能会偶尔出现假阳性结果,但总的来说,在检测程序中的这类问题时发现它相当有效。

C ++ 17标准将在更多情况下定义操作数的评估顺序:特别是它要求在左侧之前评估赋值的右侧,所以上面的例子不再是未定义的。 但是这个警告仍然会警告他们,帮助人们避免编写C语言和早期C ++版本中未定义的代码。

这个标准的措辞令人困惑,因此在微妙的情况下,对序列点规则的确切含义存在一些争议。 有关问题讨论的链接,包括提出的正式定义,可以在GCC的阅读页面上找到, 网址为http://gcc.gnu.org/readings.html 。

对于C和C ++,此警告由-Wall启用。

仅对于C,在函数的返回类型为void ,使用表达式的return语句发出警告,除非表达式类型也为void 。 作为GNU扩展,除非使用-Wantantic,否则后一种情况会被接受而不会有警告。

对于C ++,即使指定了-Wno-return-type ,没有返回类型的函数也会生成诊断消息。 唯一的例外是在系统头文件中定义的main和函数。

此警告由-Wall启用。

-Wshift-overflow
-Wshift-overflow= n
警告左移溢出。 此警告在C99和C ++ 11模式(及更新版本)中默认启用。

讯享网switch ((int) (a == 4)) { … } 

C和C ++程序默认启用此警告。

switch (cond) { i = 15; … case 5: … } 

-Wswitch不可达 如果控件表达式和第一个case标签之间的声明只是一个声明,则不会发出警告:

讯享网switch (cond) { int i; … case 5: i = 5; … } 

C和C ++程序默认启用此警告。

要抑制此警告,请使用该unused属性(请参阅变量属性)。

此警告也由启用 -Wunused 和…一起 -Wextra 。

要抑制此警告,请使用该unused属性(请参阅变量属性)。

此警告也由启用 -Wunused ,这是启用的 -Wall 。

要抑制此警告,请使用该unused属性(请参阅变量属性)。

要抑制此警告,请使用该unused属性(请参阅变量属性)。

要抑制此警告,请使用该unused属性(请参阅变量属性)。

-Wunused-const-variable
-Wunused-const-variable= n
警告只要一个常量静态变量不用于声明就可以使用。 -Wunused const的变量= 1 由…启用 -Wunused可变为C,但不适用于C ++。在C中声明了变量存储,但在C ++中,这不是一个错误,因为const变量取代了#defines。

要抑制此警告,请使用该unused属性(请参阅变量属性)。

此警告由启用 -Wall 。

In order to get a warning about an unused function parameter, you must either specify -Wextra -Wunused (note that -Wall implies -Wunused ), or separately specify -Wunused-parameter .

If you want to warn about code that uses the uninitialized value of the variable in its own initializer, use the -Winit-self option.

These warnings occur for individual uninitialized or clobbered elements of structure, union or array variables as well as for variables that are uninitialized or clobbered as a whole. They do not occur for variables or elements declared volatile . Because these warnings depend on optimization, the exact variables or elements for which there are warnings depends on the precise optimization options and version of GCC used.

Note that there may be no warning about a variable that is used only to compute a value that itself is never used, because such computations may be deleted by data flow analysis before the warnings are printed.

 void store (int *i) { __atomic_store_n (i, 0, memory_order_consume); } 

-Winvalid-memory-model is enabled by default.

这些警告只能在优化编译时使用,否则GCC不会跟踪变量的状态。

这些警告是可选的,因为即使出现错误,GCC也可能无法确定代码何时正确。以下是可能发生的一个例子:

讯享网{ int x; switch (y) { case 1: x = 1; break; case 2: x = 4; break; case 3: x = 5; } foo (x); } 

如果值y始终为1,2或3,则x始终进行初始化,但GCC不知道这一点。要取消警告,您需要提供一个默认情况下的断言(0)或类似的代码。

此选项还会在非易失性自动变量被呼叫更改时发出警告longjmp。编译器只能看到呼叫setjmp。它不知道哪里longjmp会叫; 实际上,信号处理程序可以在代码中的任何位置调用它。因此,即使实际上没有问题,您也可能会收到警告,因为longjmp实际上不会在会导致问题的地方调用。

如果您声明所有永远不会返回的函数,则可以避免一些虚假警告noreturn。请参阅功能属性。

此警告由启用 -Wall 要么 -Wextra 。

-Wunknown-pragmas

pragma遇到GCC无法理解的指令时发出警告。如果使用此命令行选项,则甚至会为系统头文件中的未知编译指示发出警告。如果只有警告才被启用,情况并非如此-Wall 命令行选项。

Level 1: Most aggressive, quick, least accurate. Possibly useful when higher levels do not warn but -fstrict-aliasing still breaks the code, as it has very few false negatives. However, it has many false positives. Warns for all pointer conversions between possibly incompatible types, even if never dereferenced. Runs in the front end only.

Level 2: Aggressive, quick, not too precise. May still have many false positives (not as many as level 1 though), and few false negatives (but possibly more than level 1). Unlike level 1, it only warns when an address is taken. Warns about incomplete types. Runs in the front end only.

Level 3 (default for -Wstrict-aliasing ): Should have very few false positives and few false negatives. Slightly slower than levels 1 or 2 when optimization is enabled. Takes care of the common pun+dereference pattern in the front end: (int)&some_float . If optimization is enabled, it also runs in the back end, where it deals with multiple statement cases using flow-sensitive points-to information. Only warns when the converted pointer is dereferenced. Does not warn about incomplete types.

-Wstrict-overflow
-Wstrict-overflow= n
This option is only active when signed overflow is undefined. It warns about cases where the compiler optimizes based on the assumption that signed overflow does not occur. Note that it does not warn about all cases where the code might overflow: it only warns about cases where the compiler implements some optimization. Thus this warning depends on the optimization level.

An optimization that assumes that signed overflow does not occur is perfectly safe if the values of the variables involved are such that overflow never does, in fact, occur. Therefore this warning can easily give a false positive: a warning about code that is not actually a problem. To help focus on important issues, several warning levels are defined. No warnings are issued for the use of undefined signed overflow when estimating how many iterations a loop requires, in particular when determining whether a loop will be executed at all.

-Wstringop-overflow
-Wstringop-overflow= type
Warn for calls to string manipulation functions such as memcpy and strcpy that are determined to overflow the destination buffer. The optional argument is one greater than the type of Object Size Checking to perform to determine the size of the destination. See Object Size Checking . The argument is meaningful only for functions that operate on character arrays but not for raw memory functions like memcpy which always make use of Object Size type-0. The option also warns for calls that specify a size in excess of the largest possible object or at most SIZE_MAX / 2 bytes. The option produces the best results with optimization enabled but can detect a small subset of simple buffer overflows even without optimization in calls to the GCC built-in functions like __builtin_memcpy that correspond to the standard functions. In any case, the option warns about just a subset of buffer overflows detected by the corresponding overflow checking built-ins. For example, the option will issue a warning for the strcpy call below because it copies at least 5 characters (the string “blue” including the terminating NUL) into the buffer of size 4.

enum Color { blue, purple, yellow }; const char* f (enum Color clr) { static char buf [4]; const char *str; switch (clr) { case blue: str = "blue"; break; case purple: str = "purple"; break; case yellow: str = "yellow"; break; } return strcpy (buf, str); // warning here } 

Option -Wstringop-overflow=2 is enabled by default.

-Wstringop-overflow
-Wstringop-overflow=1
The -Wstringop-overflow=1 option uses type-zero Object Size Checking to determine the sizes of destination objects. This is the default setting of the option. At this setting the option will not warn for writes past the end of subobjects of larger objects accessed by pointers unless the size of the largest surrounding object is known. When the destination may be one of several objects it is assumed to be the largest one of them. On Linux systems, when optimization is enabled at this setting the option warns for the same code as when the _FORTIFY_SOURCE macro is defined to a non-zero value.

In the following example, the call to strncat specifies a bound that is less than the length of the source string. As a result, the copy of the source will be truncated and so the call is diagnosed. To avoid the warning use bufsize - strlen (buf) - 1) as the bound.

讯享网 void append (char *buf, size_t bufsize) { strncat (buf, ".txt", 3); } 

As another example, the following call to strncpy results in copying to d just the characters preceding the terminating NUL, without appending the NUL to the end. Assuming the result of strncpy is necessarily a NUL-terminated string is a common mistake, and so the call is diagnosed. To avoid the warning when the result is not expected to be NUL-terminated, call memcpy instead.

 void copy (char *d, const char *s) { strncpy (d, s, strlen (s)); } 

In the following example, the call to strncpy specifies the size of the destination buffer as the bound. If the length of the source string is equal to or greater than this size the result of the copy will not be NUL-terminated. Therefore, the call is also diagnosed. To avoid the warning, specify sizeof buf - 1 as the bound and set the last element of the buffer to NUL .

讯享网 void copy (const char *s) { char buf[80]; strncpy (buf, s, sizeof buf); ... } 

在字符数组旨在存储字节序列且不终止NUL的情况下,可以使用属性nonstring对其进行注释以避免此警告。但是,这样的数组对于期望NUL终止字符串的函数不适合。为了帮助检测这种阵列的意外滥用,GCC发出警告,除非它能证明使用是安全的。请参阅常用变量属性。

-Wsuggest-attribute=pure
-Wsuggest-attribute=const
-Wsuggest-attribute=noreturn
-Wsuggest-attribute=malloc
发出警告的功能,可能是属性候选人pure,const或noreturn或malloc。编译器只警告在其他编译单元或(在的情况下,可见功能pure和const),如果它不能证明该功能正常返回。如果函数不包含无限循环或通过抛出,调用abort或陷印异常返回,函数将正常返回。该分析需要选项-fipa纯const的 ,这在默认情况下是启用的 -O和更高。更高的优化级别可以提高分析的准确性。

-Wsuggest-attribute=format
-Wmissing-format-attribute
警告可能是format属性候选的函数指针。请注意,这些只是可能的候选人,而不是绝对的。 GCC猜测具有format赋值,初始化,参数传递或返回语句中使用的属性的函数指针format在结果类型中应该具有相应的属性。即分配或初始化的左侧,参数变量的类型或包含函数的返回类型应分别具有一个format属性以避免警告。

海湾合作委员会也警告可能是format属性候选的函数定义。再次,这些只是可能的候选人。GCC猜测format属性可能适用于任何调用类似vprintfor 的函数vscanf,但这可能不总是这种情况,并且format可能不会检测到属性适当的某些函数。


讯享网

例如,一个有界的情况alloca可能是:

void func (size_t n) { void *p; if (n <= 1000) p = alloca (n); else p = malloc (n); f (p); } 

在上面的示例中,传递-Walloca-larger-than=1000不会发出警告,因为调用alloca已知最多为1000个字节。但是,如果-Walloca-larger-than=500通过,编译器会发出警告。

另一方面,无界用途是alloca没有控制谓词约束其整数参数的用法。例如:

讯享网 void func() { void * p = alloca(n); f(p); } 

如果-Walloca-larger-than=500通过,上述情况会触发警告,但这次是因为缺少边界检查。

请注意,即使看起来正确的代码涉及有符号整数可能会导致警告:

void func (signed int n) { if (n < 500) { p = alloca (n); f (p); } } 

在上面的例子中,n可能是负数,导致比期望的参数更隐含地投入到alloca调用中。

此选项还会alloca在循环中使用时发出警告。

此警告未启用 -Wall ,并且只在有效时才有效 -ftree-VRP 是活动的(默认为 -02 以上)。

也可以看看 -Wvla-greater-than = n 。

-Warray-bounds
-Warray-bounds= n
该选项仅在激活时才有效 -ftree-VRP 是活动的(默认为 -02以上)。它警告下标总是超出范围的数组。此警告由启用-Wall 。

讯享网int n = 5; … if ((n > 1) == 2) { … } 

此警告由启用 -Wall 。

此警告由启用 -Wall 。

if (p != NULL) return 0; else return 0; 

当两个分支只包含一个空语句时它不会发出警告。此警告还警告有条件的操作员:

int i = x?* p:* p;
-Wduplicated-cond
在if-else-if链中警告重复的条件。例如,警告以下代码:

讯享网if (p->q != NULL) { … } else if (p->q != NULL) { … } 

-Wno-discarded-array-qualifiers (C and Objective-C only)
不要警告在指针目标数组上的类型限定符是否被丢弃。通常,编译器会警告const int ()[]变量是否传递给了一个带int ()[]参数的函数。这个选项可以用来抑制这样的警告。

int i = 1; … if (i > i) { … } 

此警告还会警告总是评估为真或假的比特比较,例如:

讯享网if ((a & 16) == 10) { … } 

将永远是错误的。

此警告由启用 -Wall 。

这背后的想法是,有时候对于程序员来说,将浮点值视为对无限精确实数的逼近是很方便的。如果你这样做,那么你需要计算(通过分析代码,或者以其他方式)计算引入的最大或可能的最大误差,并且在执行比较时允许它(并且当产生输出时,但是这是一个不同的问题)。特别是,您应该检查两个值是否具有重叠范围,而不是测试相等性。这是通过关系运算符完成的,所以平等比较可能是错误的。

在宏体中出现在字符串文字中的宏参数。在传统的C宏替换发生在字符串文字中,但在ISO C中不。
在传统的C中,一些预处理器指令不存在。传统的预处理器只有在’#‘出现在第1行上。因此-Wtraditional 警告传统C理解但忽略的指令,因为’ #‘不会显示为该行的第一个字符。它也建议你#pragma通过缩进来隐藏传统C无法理解的指令。一些传统的实现不承认#elif,所以这个选项建议完全避免它。
类似于函数的宏,不带参数出现。
一元加运算符。
‘’ ü ‘整数常量后缀,或’ F ’ 要么 ’ 大号’浮点常量后缀。(传统的C确实支持’大号 ‘后缀在整型常量上。)注意,这些后缀出现在大多数现代系统的系统头文件中定义的宏中,例如’ _Min ‘/’ _MAX’宏’ <limits.h>。在用户代码中使用这些宏通常可能会导致虚假警告,但是GCC的集成预处理器有足够的上下文来避免在这些情况下发出警告。
一个块在外部声明的函数,然后在块结束后使用。
一个switch语句有一个类型的操作数long。
一个非static函数声明static。这个构造不被一些传统的C编译器接受。
整型常量的ISO类型与传统类型具有不同的宽度或符号。如果该常数的基数为十,则仅发出该警告。即,通常表示位模式的十六进制或八进制值没有被警告。
检测到ISO字符串串联的用法。
自动聚合的初始化。
标识符与标签冲突。传统C缺乏标签的单独名称空间。
初始化工会。如果初始值设定为0,则省略警告。这是在假设用户代码中的零初始化符出现在例如__STDC__以避免丢失初始化器警告并且在传统C情况下依靠默认初始化为零的假设下完成的。
原型在固定/浮点值之间进行转换,反之亦然。与传统C编译时缺少这些原型会导致严重问题。这是可能的转换警告的一个子集; 为全套使用-Wtraditional转换 。
使用ISO C风格函数定义。这个警告是有意不发出原型声明或可变参数的功能,因为这些ISO C功能使用libiberty传统C兼容性宏时出现在你的代码,PARAMS和VPARAMS。对于嵌套函数,此警告也被绕过,因为该功能已经是GCC扩展,因此与传统的C兼容性无关。
-Wtraditional-conversion (C and Objective-C only)
如果原型导致类型转换与在没有原型的情况下发生相同的参数不同,则发出警告。这包括固定点到浮动的转换,反之亦然,转换会改变定点参数的宽度或符号,除非与默认提升相同。

 for(SomeIterator i = SomeObj.begin(); i!= SomeObj.end(); ++ i) { for(int i = 0; i <N; ++ i) { ... } ... } 

由于上述i示例中的两个变量具有不兼容的类型,因此仅启用-Wshadow =兼容本地不会发出警告。因为它们的类型是不兼容的,所以如果程序员意外地使用一个来代替另一个,那么类型检查会捕获它并发出错误或警告。所以在这种情况下不要警告(关于影子)不会导致未被发现的错误。使用这个标志而不是-Wshadow =本地 可能会减少故意投影引发的警告数量。

此警告由启用 -Wshadow =本地 。

这个消息符合输出 -fstack使用率 。

如果堆栈使用情况完全是静态的,但超过了指定的数量,则是:
警告:堆栈使用量为1120字节( warning: stack usage is 1120 bytes)
如果堆栈使用情况(部分)是动态的但有界限的,则是:
警告:堆栈使用可能是1648字节(warning: stack usage might be 1648 bytes)
如果堆栈使用情况(部分)是动态的并且不受限制,那么:
警告:堆栈使用可能是无限的( warning: stack usage might be unbounded)
-Wunsafe-loop-optimizations
警告如果循环无法优化,因为编译器无法假设循环索引的范围内的任何内容。同-funsafe循环的优化 警告如果编译器做出这样的假设。

通常这只会警告全局分配函数,但是 -Waligned全新=所有 也警告类成员分配功能。

-Wplacement-new
-Wplacement-new= n
警告使用未定义行为放置新表达式,例如在小于对象类型的缓冲区中构造对象。例如,下面的放置新表达式被诊断,因为它试图在只有64个字节大的缓冲区中构造64个整数的数组。

讯享网 char buf [64]; new(buf)int [64]; 

该警告默认启用。

 struct S {int n,a [1]; }; S * s =(S *)malloc(sizeof * s + 31 * sizeof s-> a [0]); new(s-> a)int [32](); 
讯享网 struct S {int n,a []; }; S * s =(S *)malloc(sizeof * s + 32 * sizeof s-> a [0]); new(s-> a)int [32](); 
const char *p = foo (); if (p == '\0') return 42; 

请注意,上面的代码在C ++ 11中无效。

该警告默认启用。

-Wcomment
-Wcomments
每当评论开始序列’ / * ‘出现在’ / * ‘评论,或者每当一个反斜线换行符出现在’ //'评论。此警告由启用-Wall 。

这个选项是隐含的 -Wall。如果-Wall没有给出,除非启用三字母,否则该选项仍然有效。要获得没有警告的三字母转换,但要获得另一个-Wall 警告,使用’ -trigraphs -Wall -Wno-trigraphs ”。

内建的宏,命令行中定义的宏和包含文件中定义的宏不会被警告。

注意:如果实际使用宏,但仅用于跳过的条件块,则预处理器将其报告为未使用。为了避免在这种情况下发出警告,可以通过例如将其移动到第一个跳过的块中来改善宏定义的范围。或者,您可以提供一个类似以下内容的虚拟用途:

讯享网 #if defined the_macro_causing_the_warning #endif 
 #if FOO ... #else FOO ... #endif FOO 

第二和第三位FOO应该在评论中。此警告默认开启。

在进行以非安全方式引入类型限定符的演员时也会发出警告。例如,铸造char 到const char 是不安全的,因为在这个例子:

讯享网 /* p is char value. */ const char q = (const char ) p; /* Assignment of readonly string to const char * is OK. */ *q = "string"; /* Now char pointer points to read-only memory. */ p = 'b'; 

编译C ++时,警告关于从字符串文字到不再使用的转换char *。C ++程序默认启用此警告。

-Wcatch-value
-Wcatch-value= n (C++ and Objective-C++ only)
警告关于捕捉处理程序,不通过参考捕获。同-Wcatch值= 1 (要么 -Wcatch价值简称)警告关于被值捕获的多态类类型。同-Wcatch值= 2警告所有类型的价值。同-Wcatch值= 3 警告所有没有被引用捕获的类型。 -Wcatch价值 由…启用 -Wall 。

对于C ++,也会警告混淆用户定义转换的重载解析; 以及从不使用类型转换运算符的转换:转换为void,相同类型,基类或对它们的引用。在C ++中,有关已签名和未签名整数之间转换的警告在默认情况下是禁用的,除非-Wsign转换 被明确启用。

{ if (a) if (b) foo (); else bar (); } 

在C / C ++中,每个else分支都属于最内层的可能if语句,在本例中为if (b)。这通常不是程序员所期望的,正如上例中程序员选择的缩进所示。当可能出现这种混淆时,GCC会在指定此标志时发出警告。为了消除这个警告,在最里面的if语句周围添加显式大括号,这样就else不可能属于这个封闭if。生成的代码如下所示:

讯享网{ if (a) { if (b) foo (); else bar (); } } 

此警告由启用 -Wparentheses 。

-Wjump门柱-INIT 包含在内 -Wc ++ - COMPAT。它可以被禁用-Wno跳门柱-INIT 选项。

 void operator delete(void *)noexcept; void operator delete [](void *)noexcept; 

而没有定义相应大小的释放函数

讯享网 void operator delete(void *,std :: size_t)noexcept; void operator delete [](void *,std :: size_t)noexcept; 

或相反亦然。启用-Wextra 随着 -fsized,释放 。

 void make_file(const char * name) { char path [PATH_MAX]; strncpy(path,name,sizeof path - 1); strncat(path,“.text”,sizeof“.text”); ... } 

该 -Wsizeof指针-memaccess 选项由启用 -Wall 。

讯享网extern int a; if (a < 0 && a < 0) { … } 
int a; … if (!a > 1) { … } 

可以通过将LHS包括在括号中来抑制警告:

讯享网if ((!a) > 1) { … } 

此警告由启用 -Wall 。

 void foo(bar){} 

此警告也由启用 -Wextra 。

讯享网 struct s {int f,g,h; }; struct sx = {3,4}; 

此选项不会警告指定的初始化程序,因此以下修改不会触发警告:

 struct s {int f,g,h; }; struct sx = {.f = 3,.g = 4}; 

在C中,这个选项不会警告通用零初始化器’ {0} “:

讯享网 struct s {int f,g,h; }; struct sx = {0}; 

同样,在C ++中,此选项不会警告空{}初始化程序,例如:

 struct s {int f,g,h; }; sx = {}; 

此警告包含在中 -Wextra。获得其他-Wextra 没有这个警告,使用 -Wextra -Wno-missing-field-initializers 。

GCC支持四级警告。默认是-Wnormalized = NFC,它警告任何非ISO 10646“C”规范化形式的标识符NFC。NFC是大多数用途的推荐形式。这相当于-Wnormalized 。

不幸的是,ISO C和ISO C ++在标识符中允许有一些字符在变成NFC时不允许用于标识符。也就是说,无法在便携式ISO C或C ++中使用这些符号,并且在NFC中使用所有标识符。-Wnormalized = ID抑制这些字符的警告。希望未来版本的标准能够纠正这个问题,这就是为什么这个选项不是默认选项。

您可以通过书写来关闭所有角色的警告 -Wnormalized =无 要么 -Wno标准化。如果您使用其他规范化方案(如“D”),则只应执行此操作,否则您可以轻松创建几乎不可能看到的错误。

ISO 10646中的一些字符具有不同的含义,但在某些字体或显示方法中看起来完全相同,尤其是在应用格式化之后。例如\u207F,“SUPERSCRIPT LATIN SMALL LETTER N”,就像一个n放在上标中的常规一样显示。ISO 10646定义了NFKC规范化方案,将所有这些转换为标准格式,如果您使用的代码不在NFKC中,GCC会发出警告-Wnormalized = nfkc。此警告与包含字母O的每个标识符的警告相当,因为它可能与数字0混淆,所以不是默认值,但如果编程环境无法修复以显示这些内容,则可能作为本地编码约定有用字符清晰。

此警告包含在中 -Wextra。获得其他-Wextra 没有这个警告,使用 -Wextra -Wno-override-init 。

讯享网 struct foo { int x; char a,b,c,d; } __attribute __((packed)); 结构栏{ char z; struct foo f; }; 
 struct foo { char a:4; char b:8; } __attribute__((packed)); 

该警告默认启用。使用-Wno-填充位字段,COMPAT 禁用此警告。

讯享网 struct __attribute__((aligned(8)))S8 {char a [8]; }; struct __attribute__((packed))S { struct S8 s8; }; 

此警告由启用 -Wall 。

 void foo(void) { char a [] =“abcd1234”; strcpy(a,a + 4); ... } 

该 -Wrestrict 选项检测到一些简单重叠的情况,即使没有进行优化,但最适用于 -02以上。它包含在中-Wall 。

编译器使用各种启发式来确定是否内联一个函数。例如,编译器考虑了内联函数的大小以及当前函数中已经完成的内联量。因此,源程序中看似微不足道的变化可能会导致警告-Winline 出现或消失。

offsetof在未来的C ++标准版本中,这些限制可能会放宽。

请注意,GCC可能会将已知值的小型可变长度数组优化为普通数组,因此可能无法触发此警告。

此警告未启用 -Wall ,并且只在有效时才有效 -ftree-VRP 是活动的(默认为 -02 以上)。

也可以看看 -Walloca-greater-than = n 。

该限制适用于字符串常量级联之后,并且不计算尾随NUL。在C90中,限制为509个字符; 在C99中,它被提升到了4095. C ++ 98没有规定最小最大规范,所以我们不用诊断C ++中的超长字符串。

这个选项是隐含的 -Wpedantic ,并可以禁用 -Wno-超长串 。

小讯
上一篇 2025-03-30 22:04
下一篇 2025-01-04 21:11

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/18645.html