-Wall,-Wextra开启的告警
- -Waddress:可能是无意义的地址使用方式(包括函数地址、变量地址等)。
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
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
Target* Cast( Base* from)
{
if( from->GetType() != Target::MagicValue )
throw new std::exception();
return static_cast( from );
}
void test()
{
ClassOne obj;
Cast( &obj );
}
warning: comparison between 'enum Magic' and 'enum ClassOne::' [-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
add(int a, int b) { //函数没有声明返回类型
return a + b;
}
int test() {
int a = 0;
int b = 0;
int c = 0;
int d = 0;
c = add(a, b);
d = sub(a, b); //未声明sub的函数原型
return 0;
}
warning: return type defaults to `int' [-Wimplicit-int]
- -Wimplicit-function-declaration:隐式声明(通常为函数遗漏了声明)。
#include
add(int a, int b) { //函数没有声明返回类型
return a + b;
}
int test() {
int a = 0;
int b = 0;
int c = 0;
int d = 0;
c = add(a, b);
d = sub(a, b); //未声明sub的函数原型
return 0;
}
warning: implicit declaration of function `sub' [-Wimplicit-function-declaration]
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]
#include
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
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
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
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(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::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
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]