【gcc】warning信息梳理

10 篇文章 0 订阅

-Wall,-Wextra开启的告警

void f (int, int, int, bool, int *);
void g (int i)
{
f (1, 2, 3, &i, &i);
}
# warning: the address of ‘i’ will always evaluate as 'true' [-Waddress]

• -Warray-bounds：数组越界告警，如数组下标访问越界。

int array[3];
void foo(int n)
{
// 没有对入参进行校验，可能出现数组访问越界
for (int i = 0; i < n; ++i)
for (int j = 0; j < i; ++j)
if (array[i] == array[j])
array[i + j] = 0;
}
# warning: array subscript is above array bounds [-Warray-bounds]

• -Wbool-compare：布尔值与整形数据比较。

int
fn1 (int a, int b)
{
return ((a && b) <= 4);
}
# warning: comparison of constant ‘4’ with boolean expression is always true[-Wbool-compare]

• -Wbool-operation：对布尔类型进行加减等操作。

int main(int argc, char **argv)
{
bool a = true;
bool b = a++;
bool c = ++b;
bool d = argc;
bool e = a & argc;
bool f = b | argc;
bool g = c ^ argc;
f &= argc;
g |= argc;
e ^= argc;
if (f1(argc))
e--;
else
--e;
if (!!argc)
return ((argv != NULL) ? d : ((f > g) ? e : (f << g)));
else
return f2(argc);
}
# warning: increment of a boolean expression [-Wbool-operation]

• -Wc++11-compat -Wc++14-compat：版本兼容告警，如nullptr在C++11之前可以作为标识符使用，而在C++11之后，是关键字。

#define S(a) #a
const char* s = S(and);
# warning: identifier "and" is a special operator name in C++[-Wc++11-compat]

• -Wcatch-value：try…catch…语句中的error部分用值而非引用捕获异常.

try
{
new_idx = aReorderMap.at( orig_idx );
}
catch( std::out_of_range )
{
new_idx = orig_idx;
}
# warning: catching polymorphic type ‘class std::out_of_range’ by value [-Wcatch-value=]

• -Wchar-subscripts：用有符号的char类型作为数组的下标。

int a[256];
int A(char c) { return a[c];      }
# warning: array subscript has type ‘char’ [-Wchar-subscripts]

• -Wcomment：注释语句中含有编译器预处理所需的特殊字符，使用-Wcomment会给出警告。不要小觑这些马虎代码，它很可能会影响程序的运行结果。

#include<stdio.h>
int main()
{
int      a        = 1;
int      b        = 2;
int      c        = 0; // ok just test\
c = a + b;

/*
* 这里我们期待c = 3
* /* 但实际上输出c = 0
*/
printf("the c is %d\n", c);
return 0;
}
# warning: multi-line comment [-Wcomment]

• -Wduplicate-decl-specifier：声明语句有异议。

extern uint8_t CalculateChecksum(const communicationBlock_t const *messageBlock);
# duplicate ‘const’ declaration specifier [-Wduplicate-decl-specifier]

• -Wenum-compare：不同的枚举类型进行比较。

enum Magic {
One, Two, Three
};
class Base {
public:
virtual Magic GetType() = 0;
};
class ClassOne : public Base {
public:
enum {
MagicValue = One
};
Magic GetType() { return One; }
};
class ClassTwo : public Base {
public:
enum {
MagicValue = Two
};
Magic GetType() { return Two; }
};
template
<class Target>
Target* Cast( Base* from)
{
if( from->GetType() != Target::MagicValue )
throw new std::exception();
return static_cast<Target*>( from );
}
void test()
{
ClassOne obj;
Cast<ClassOne>( &obj );
}
# warning: comparison between 'enum Magic' and 'enum ClassOne::<anonymous>' [-Wenum-compare]

• -Wenum-conversion：一个枚举类型隐式转换为另一个类型。

enum xpto
{
A = 0,
B = 1,
X = 512
};
extern void print (unsigned int);
unsigned char bar (enum xpto a)
{
return a;
}
# warning: implicit conversion from enum to char [-Wenum-conversion]

• -Wformat：检查printf和scanf等格式化输入输出函数的格式字符串与参数类型的匹配情况，如果发现不匹配则发出警告。某些时候格式字符串与参数类型的不匹配会导致程序运行错误，所以这是个很有用的警告选项。

int
ENTITYget_CORBAname (Entity ent)
{
static char newname [BUFSIZ];
strcpy( newname, ENTITYget_name(ent) );
newname[0] = ToUpper (newname [0]);
return newname;
}
fprintf(file, "\n//\t%s_ptr create_TIE();\n\tIDL_Application_instance_ptr create_TIE();\n",
ENTITYget_CORBAname(entity));
# warning: format ‘%s’ expects argument of type ‘char *’, but argument 3 has type ‘int’ [-Wformat]

• -Wformat-overflow：格式化字符串可能造成缓冲区溢出，格式化字符串需要进行缓冲区溢出检查。

sprintf(newname, "%s%s", dirname, basename);
# warning: ‘.tmpconfig.’ directive writing 11 bytes into a region of size between 1 and 4097 [-Wformat-overflow=]

• -Wformat-truncation ：格式化字符串过程中可能导致截断错误。

struct S {
char b[3];
};
char buf[2];
void f(struct S const * s)
{
assert(strlen(s->b) == 1);
(void) snprintf(buf, sizeof (buf), "%s", s->b);
}
# warning: ‘snprintf’ output may be truncated before the last format character[-Wformat-truncation=]

• -Wint-in-bool-context：在应该使用布尔类型的地方，使用整形表达式。

for (a = 0; 1 << a; a++)
{}
# warning: int in bool context [-Wint-in-bool-context]

• -Wimplicit：-Wimplicit-int和-Wimplicit-function-declaration两个警告选项的集合，参见-Wimplicit-int，-Wimplicit-function-declaration

• -Wimplicit-int：隐式的转化为整形类型。

#include<stdio.h>
add(int a, int b) { //函数没有声明返回类型
return a + b;
}
int test() {
int      a        = 0;
int      b        = 0;
int      c        = 0;
int      d        = 0;
d = sub(a, b); //未声明sub的函数原型
return 0;
}
# warning: return type defaults to int' [-Wimplicit-int]

• -Wimplicit-function-declaration：隐式声明（通常为函数遗漏了声明）。

#include<stdio.h>
add(int a, int b) { //函数没有声明返回类型
return a + b;
}
int test() {
int      a        = 0;
int      b        = 0;
int      c        = 0;
int      d        = 0;
d = sub(a, b); //未声明sub的函数原型
return 0;
}
# warning: implicit declaration of function sub' [-Wimplicit-function-declaration]

• -Winit-self：使用自身进行初始化。

int f()
{
int i = i;
return i;
}
# warning: init 'i' with 'i' [-Winit-self]

• -Wlogical-not-parentheses：逻辑没有显式的指明优先级，导致可能的符号优先级错误。

int a;
…
if (!a > 1) { … }
# warning: logic not used on the left hand of the comparision [-Wlogical-not-parentheses]

• -Wmain：可疑的main函数类型检查。

#include <stdio.h>
void main ()
{
int x;
for(x=1;x<=10;x++)
{
printf("%d\n",x);
}
}
# warning: function 'main' return type 'void', should be 'int' [-Wmain]

• -Wmaybe-uninitialized：变量声明后，在使用之前，经历了一些条件分支，其中有一些分支对该变量进行了赋值，另一些分支没有赋值。

extern void dostuff(void);
int test(int arg1, int arg2)
{
int ret;
if (arg1) ret = arg2 ? 1 : 2;
dostuff();
if (arg1) return ret;
return 0;
}
# warning: ‘ret’ may be used uninitialized in this function [-Wmaybe-uninitialized]

• -Wmemset-elt-size：memset如果第一个参数引用一个数组，并且第三个参数是一个等于元素数的数字，但不等于内存中数组的大小，则警告对内置函数的可疑调用。这表明用户已经省略了元素大小的乘法。

struct A {
A()
{
memset(&buff, 0xff, sizeof(buff));
}
int buff[0];
};
# warning: 'memset' used with length equal to number of elements without multiplication by element size [-Wmemset-elt-size]

• -Wmemset-transposed-args：memset使用时，第三个参数为0，而第二个参数非0，编译器认为可能是开发人员参数顺序填写错误触发此告警。

memset(buf, sizeof(buf), 0);
# warning: 'memset' used with constant zero length parameter; this could be due to transposed parameters [-Wmemset-transposed-args]

• -Wmisleading-indentation：当代码的缩进不反映块结构时发出警告。 具体而言，针对if ， else ， while和for子句发出警告，其中警告语句不使用大括号，后跟具有相同缩进的未保护语句。

  if (some_condition())
foo();
bar();  // Gotcha: this is not guarded by the "if".
# warning: this ‘if’ clause does not guard... [-Wmisleading-indentation]

• -Wmissing-attributes：当函数声明缺少一个或多个属性时，产生告警。并且这种属性的缺少，可能会对生成的代码的正确性或效率产生负面影响。

__attribute__ ((noreturn)) void f (void) { __builtin_abort (); }
__attribute__ ((alias ("f"))) void fa (void);
void g (void) { }
__attribute__ ((alias ("g"), noreturn)) void ga (void);
# warning: ‘fa’ specifies less restrictive attribute than its target ‘f’: ‘noreturn’ [-Wmissing-attributes]

• -Wmissing-braces：如果聚合或联合初始值设定项没有完全包围，则发出警告。

int main()
{
struct { int w; struct { int x, y; } ss; } s = { 1, .ss = 2, 3 };
(void)s;
}
# warning: missing braces around initializer [-Wmissing-braces]

• -Wmultistatement-macros：不安全的宏定义。

#define DOIT x++; y++
if (c) DOIT;
# warning: macro 'DOIT' not safe [-Wmultistatement-macros]

• -Wnarrowing：缩窄转换，从int转为short可能会导致整形截断。

int i = -1;
char p = i;
# warning: narrowing conversion '-1' from int to char [-Wnarrowing]

• -Wnonnull：向接受非空指针的函数传递了nullptr。

main()
{
if(fork()==0)
{
printf("a");
execlp("./file1",0);
printf("b");
}
printf("c")
}
# warning: null argument where non-null required (argument 2) [-Wnonnull]

• -Wnonnull-compare：在已经标注了非空指针参数的函数中，再次判断是否为空。

void foo(int& x)
{
bool b1 = (&x) == nullptr;
bool b2 = &x == nullptr;
int* ptr = &x;
bool b3 = ptr == nullptr;
}
# warning: nonnull argument ‘x’ compared to NULL [-Wnonnull-compare]

• -Wopenmp-simd：采用openmp并行模型，被其他模型覆盖时，产生告警

• -Wparentheses：如果在某些上下文中省略了括号，例如当预期是bool值，却进行了赋值运算时，或者运算符嵌套。

#include <stdio.h>
int main(void)
{
int a = 1;
int b = 2;
if (a = b)
{
//do nothing
}
return 0;
}
# warning: suggest parentheses around assignment used as truth value [-Wparentheses]

• -Wpessimizing-move：不规范的std::move用法，例如在return语句中对局部变量进行move操作。

struct A {}
A test() {
A a = std::move(A());  // warn since A() is a pr-value
return std::move(a);  // warn since a is a local variable
}
# warning：move local variable in return statement [-Wpessimizing-move]

• -Wpointer-sign：指针指向的内容分别为有符号和无符号类型。

#include <limits.h>
void foo(void) {
char *pc = 0;
#if CHAR_MIN < 0
/* plain char is signed but incompatible with signed char */
signed char *psc = pc;
#else
/* plain char is unsigned but incompatible with unsigned char */
unsigned char *puc = pc;
#endif
}
# warning: pointer targets in initialization differ in signedness [-Wpointer-sign]

• -Wreorder：初始化列表的初始化顺序与类成员声明的顺序不一致，会产生重排列。

class A
{
public:
A(int a, int b);
private:
int two;
int one;
}
A::A(int a, int b)
:one(a),
two(b)
{}
# warning: 'A::one' will be initialized after [-Wreorder]

• -Wrestrict：内存相关操作超出限制，导致截断或溢出。

#include <string.h>
struct S {
int n;
void * p;
};
void f(struct S * a, size_t n)
{
size_t i = 0, j = 0;
for (; i != n; ++i) {
if (a[i].n == 0) {
if (i != j) {
memcpy(&a[j], &a[i], sizeof (struct S));
}
++j;
}
}
}
# warning: ‘memcpy’ accessing 16 bytes at offsets [0, 8] and [0, 8] overlaps between 8 and 16 bytes at offset [0, 8] [-Wrestrict]

• -Wreturn-type：函数有返回值，但函数体个别地方没有返回值(特别是有if判断，可能忘记在else添加返回值)。

int foo()
{
if(a==1)
{
return ok;
}
// no return here
}
# warning: missing return statement [-Wreturn-type]

• -Wsign-compare：无符号和有符号整形比较，会发生隐式转换。

int f (int i)
{
unsigned char c = i ? (-__SCHAR_MAX__ - 1) : 1U;
return c;
}
# warning: signed and unsigned type in conditional expression [-Wsign-compare]

• -Wsizeof-pointer-div：使用除法求数组元素大小，sizeof (ptr) / sizeof (ptr[0])，如果ptr是指针，而非数组。

sizeof (ptr) / sizeof (ptr[0])  // 如果ptr不是数组，而是指针将产生告警
# warning: division ‘sizeof (ptr) / sizeof (ptr[0])’ does not compute the number of array elements [-Wsizeof-pointer-div]

• -Wsizeof-pointer-memaccess：对指针类型进行sizeof运算，作为内存操作函数的大小参数。

void f1(int *dst, int *src)
{ __builtin_memcpy(dst, src, sizeof(int *)); }
# warning: argument to ‘sizeof’ in ‘__builtin_memcpy’ call is the same pointer type ‘int *’ as the destination; expected ‘int’ or an explicit length [-Wsizeof-pointer-memaccess]

• -Wstrict-aliasing：对违反strict-aliasing规则的代码产生告警，例如将一个float类型的指针，指向一块存储了整形数字的内存空间。

• -Wstrict-overflow：

void ABSTest(int64_t value1) {
uint64_t value = static_cast<uint64_t>(value1 < 0 ? 0 - value1 : value1);
std::cout << "value " << value;
if (value < 2ul)
std::cout << " less than " << 2 << "?!\n";
else
std::cout << " compare correct\n";
}
int main()
{
int64_t value1 = std::numeric_limits<int64_t>::min();
ABSTest(value1);
}
# warning: assuming signed overflow does not occur when simplifying conditional [-Wstrict-overflow]

• -Wswitch：switch语句检查某个枚举类型，但是没有用case列出该枚举类型所有的枚举值或switch没有default时。

• -Wtautological-compare：对于比较结果恒定为true或false的语句进行告警。

int i = 1;
if (i > i)
{ … }
# warning: if always equals to false [-Wtautological-compare]

• -Wtrigraphs：存在会被编译器替换的三字符组。

int main(int argc, char **argv) ??<
char buf??(100??) = ??< 0 ??>;
printf("??/ ??' ??( ??) ??! ??< ??> ??-\n");
return 0;
??>
# warning: trigraph ??= ignored, use -trigraphs to enable [-Wtrigraphs]

• -Wuninitialized：变量在使用前未初始化。

• -Wunknown-pragmas：未知的#pragma语句，例如在gcc中使用vc++语法。

#pragma comment(lib,"winmm.lib")
# warning: ignoring #pragma comment [-Wunknown-pragmas]

• -Wunused-function：声明但未使用函数。

• -Wunused-label：未使用的标签，未使用的标签，比如用goto会使用label，但在删除goto语句时，忘了删除label。

• -Wunused-value：表达式或函数有返回值，但是未被使用。

#include <stdio.h>
int main()
{
int i;
int j;
for(i=32,j=2;i++;i<256)
{
if((i%16==0)
{
printf("\n%d:",j);
j++;
}
printf("%c ",i);
}
return 0;
}
# warning: statement with no effect [-Wunused-value]

• -Wunused-variable：变量定义后没有使用。

• -Wvolatile-register-var：寄存器变量被修饰为volatile类型。

• -Wzero-length-bounds：引用了大小为0的数组。

struct A { int n, a[0]; };
struct B { struct A a; int x; };
struct B b;
int f0 (void)
{
b.a.a[1] = 1;
int t = b.x;
b.a.a[1] = 0;
return b.x - t;
}

int f1 (struct B *p)
{
p->a.a[1] = 1;
int t = p->x;
p->a.a[1] = 0;
return p->x - t;
}
# warning: array subscript 1 is outside the bounds of an interior zero-length array ‘int[0]’ [-Wzero-length-bounds]

• 1
点赞
• 14
收藏
觉得还不错? 一键收藏
• 打赏
• 0
评论
08-01 229
04-05 88
11-06 379
01-09 7148
04-14 5659
11-12 2269
12-03 974
08-12
03-01 1万+
10-12 8834

ʚ兔子的先森ɞ

¥1 ¥2 ¥4 ¥6 ¥10 ¥20

1.余额是钱包充值的虚拟货币，按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载，可以购买VIP、付费专栏及课程。