本帖总结编译出现的各种warnning和error的原因,持续更新。对本帖中出现的示例函数作个简单的说明:
- char* get_char_pointer() : 返回一个char*类型。
- int poiner_func(char* p):接收char* 类型的指针。
下面开始记录各种编译警告和错误
- 警告:pointless comparison of unsigned integer with a negative constant
大意为:一个无意义的比较无符号整型和一个负数常量。
调用者:uint8 len; if(len < -1){return;} 比较正数小于-1 毫无意义。 - 警告:implicit declaration of function ‘xxxxxxx’
代表隐式声明函数,出现在.c文件没有包含对应函数的.h文件就直接调用了那个函数,或者直接调用了在.c里实现的函数,没有在头文件里声明。这种不加头文件的情况要严令禁止。 - 警告: assignment makes pointer from integer without a cast [-Wint-conversion]
出现这个警告的原因是在使用函数之前没有对函数进行声明,未经声明的函数原型一律默认为返回int值。这样,就相当于你调用了返回值为int的函数,并将其赋给了char*、int*等等指针变量,就会出现警告。 - 警告: argument to ‘sizeof’ in ‘memset’ call is the same expression as the destination; did you mean to dereference it? [-Wsizeof-pointer-memaccess]
直译过来就是:“ memset”调用中“ sizeof”的参数与目标的表达式相同; 您是要取消引用它吗?目标表达式指的就是memset第一个参数,也就是指针,很明显提示sizeof也传入了变量指针,应该传入类型说明符和表达式。
调用者:char *str = get_char_pointer(); memset(str, 0, sizeof(str));就会出现警告。 - 警告: initialization makes integer from pointer without a cast [-Wint-conversion]
调用者:char *id = NULL, name = NULL;
name = get_char_pointer();
这样连续定义指针,导致name并未定义成指针,而是定义成了一个int型。
要么定义成char* id = NULL, *name = NULL; 要么分开定义。 - 警告: 传递‘pthread_create’的第 3 个参数时在不兼容的指针类型间转换 [-Wincompatible-pointer-types]
pthread_create原型:int pthread_create(pthread_t *tidp,const pthread_attr_t *attr,void *(*start_rtn)(void*),void *arg);
可见第三个参数返回值是void*类型,参数是void*类型,这种错误一般要么是第三个参数返回值写成了void,要么是参数不是void*。出现参数不兼容转换的警告,基本都是这个原因。
调用者:static void thread_func(void arg),
pthread_create(&pid, NULL, thread_func, NULL);
编译便会警告。 - 警告: ‘av_free_packet’ is deprecated [-Wdeprecated-declarations]
表明av_free_packet函数已经过时,不建议使用,由于库在更新迭代过程中产生新的函数,旧的函数不再建议使用,所以调用旧函数时编译会产生警告。 - 警告: 函数返回局部变量的地址 [-Wreturn-local-addr]
在一个函数里定义了一个局部变量,结束时返回这个局部变量的地址,就会出现该警告。因为局部变量是在栈中申请的空间,函数执行完后该空间会自动被释放回收,所以可能你调用这个函数,获取到的返回值并不是你想要的,可能是随机值。也可以说是返回的这个局部变量指针是一个野指针,虽然返回给你了想要的数据,但是这块内存会被别的地方malloc使用,所以最好不要返回局部变量地址,否则后果可能很严重。 - 警告: 数组下标类型为‘char’ [-Wchar-subscripts]
调用者:char index = 0; char ip[16] = {0}; for(…){ip[index++] = “192.168.1.1”;}。因为char类型的变量值可能是负数,所以可能出现ip[index]取到负数索引的数组元素,比如ip[-1],因此编译会有警告。可以把char index 换成 unsigned char index或者int index,但是至于int index为什么不报错,这个不太清楚了,可能int表示范围很大,一般不会越界变成负数吧。 - 警告: assignment discards ‘const’ qualifier from pointer target type [-Wdiscarded-qualifiers]
原因是const修饰的指针变量赋值给了普通指针变量。那么const修饰的指针变量就有可能被修改,这是不允许的。
调用者:const char* p1; char* p2 = p1; - 警告:"xxxxx"重定义
代码中某些宏定义在不同的文件中被多次定义,比如多个头文件都有如下定义:#define MAX(a,b) a>b?a:b,在编译过程中就会出现MAX重定义的问题,可将定义改为如下形式,消除警告:
#ifndef MAX
#define MAX(a,b) a>b?a:b
#endif - 警告: 反斜杠和换行为空格所分隔
调用者:#define HTTP_POST “POST %s HTTP/1.1\r\nHOST: %s:%d\r\nAccept: /\r\n”\
其原因是最后一个反斜杠后面加了空格,反斜杠换行不能加空格,否则会出现这个警告 - 错误:while running ’ aclocal ’ ,autogen.sh :1:eval:aclocal :not found
此错误发生在编译valgrind的时候执行./autogen.sh,先执行sudo apt-get install automake,安装必要的依赖和库,再执行./autogen.sh即可解决。 - 警告: assignment from incompatible pointer type
翻译:不兼容的指针类型转换,常见的使用情形如下:
char array[20] = {0}; poiner_func(&array);
编译警告:int poiner_func(char* p)需要一个char*类型的指针,而传入的是cha(*)[20]类型的指针。 - 错误: 对未指定边界的数组的使用无效
调用者:
int array_pointer_func(char (*p)[ ], int col_size)
{
....
p = (char(*)[col_size])malloc(sizeof(char) * 10);//注意数组指针分配内存的写法
strlcpy(p([idx], data, sizeof(p[idx]));//这一行报错
}
//函数修改为:
int array_pointer_func(char (*p)[64])
{
....
p = (char(*)[64])malloc(sizeof(char) * 10);
strlcpy(p([idx], data, sizeof(p[idx]));//编译通过
}
具体原因:由于第一个函数的第一个参数没有指明第二维度,虽然第二个参数传入的是第二维度的大小,但是编译器并不知道,除非在函数里给第二维度也分配空间。这里注意给数组指针分配内存的写法。
- 错误:expected declaration or statement at end of input
1、某一个函数或者变量没有在使用之前声明。
2、某个地方少了个括号。(并不一定是编译器指出错误的地方,这种情况,编译器一般会在最后一行代码报错,但错误很可能不在最后一行,要靠自己去找出来) - 警告:"usleep"和"popen"等函数隐式声明
虽然包含了头文件<unistd.h>,但是编译时仍提示隐式声明,原因是编译时加了-std=c99参数,改成-std=gnu99或者去掉即可 - error: variable ‘xxx’ has initializer but incomplete type
包含相应的头文件即可 - function declaration isn’t a prototype
因为函数原型和调用这个函数时产生了冲突,如参数类型不一样等。 在C中最常见的情况: 这时会出现了 的警告,因为在C语言中my_fn () 和 my_fn (void)是不一样的,前者可以接受任意参数,而后者不接受任何参数。 - error: invalid use of void expression
将void函数当成有返回值的函数,赋值给别的变量,导致error - error: request for member ‘Interface’ in something not a structure or union
原本是指针结构体,访问成员应该用"->“,而错误的使用了” . “访问,或者应该用”."却用了“->” - error: unterminated #ifndef
少了#endif - error: invalid digit “8” in octal constant
把 08 改成 8 就可以了, C++ 中数字前面加个 0 表示 8 进制。所以 08 表示 8 进制的 8 了,而8 进制数字范围是 0 - 7,所以 8 在 8 进制中是非法的数字,自然编译错误了。 - warning: ISO C90 forbids mixed declarations and code
变量定义之前任何一条非变量定义的语句(注意:语句是会带分号的)都会引起这个警告!将非变量的定义移到变量定义之后 即可 - error: memcpy called with overlapping regions
memcpy函数传递的参数中存在内存重叠的情况,memcpy不支持内存重叠,可以用memmove函数代替 - 交叉编译出现arm-linux-gnueabihf/bin/ld: cannot find /lib/ld-linux-armhf.so.3和arm-linux-gnueabihf/bin/ld: cannot find /lib/libc.so.6
交叉编译工具链的相应路径下是有这两个库的,却提示找不到。原因是在编译脚本里链接路径里,存在了libc.so,导致工具链编译的时候先找到了这个libc.so,找错了。比如交叉编译工具链安装路径在/opt/gcc-arm/xxx/bin/,自己的库路径是/home/xxx/lib/,在编译脚本里-L/home/xxx/lib/,而这个/home/xxx/lib/目录下也有libc.so和libc.a,导致编译出错,删除掉就好了 - 运行出现:No raw modules loaded
缺少libts相关库和配置,需要libts.so和lib/ts/etc/ts.conf和lib/ts/下的各种编译后的so,并且指明路径,比如export TSLIB_PLUGINDIR=/system/lib/ts,export TSLIB_CONFFILE=/system/lib/ts/etc/ts.conf - error: expression is not assignable(错误:表达式不可赋值)
在不该赋值的地方进行了赋值,比如错误的在if语句里写了赋值语句if(p != NULL && p = p + 1) - error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘attribute’ before ‘{’ token
语法有问题,可能是语句少了分号,但错误的地方可能不在报错对应的行,可能出现在include的头文件里面,比如定义函数最后少了分号 - warning: data definition has no type or storage class
函数在头文件声明时,少写了返回值类型 - warning: ‘struct tm’ declared inside parameter list will not be visible outside of this definition or declaration
直译过来是:警告:在参数列表中声明的“struct tm”在此定义或声明之外将不可见,实际上是这个struct tm编译器无法找到,多半是没有加头文件导致的,加上<time.h>头文件即可 - repo sync时,提示error: .repo/manifests/: contains uncommitted changes
由于./repo/manifests/仓库远程有修改,而自己本地也有修改,需要先将自己本地的更新到最新即可 - error: decrement of member ‘nr_segs’ in read-only object
可能是定义结构体时使用了const修饰,而后想修改成员变量的值导致的,去掉const即可
No pains,no gains.