隐式函数声明 [-Wimplicit-function-declaration]

什么是隐式函数声明

C语言中,函数调用前不一定要声明。如果没有声明,编译器会自动按照一种隐式声明规则,为调用函数的C代码产生汇编代码。

忽略隐式函数声明警告的危害

  • 隐式声明函数恰好在库中存在,这种情况可参考 https://www.jb51.net/article/78212.htm
  • 编译so库时会出现未定义符号,导致加载该so的程序执行出错。举例如下:
// add.c
int add(int a, int b) { 
	return a + b;
}
int sum(int a, int b, int c) { // 调用add方法,求三数和
	retunr ad(a, b) + c; // 这里本意调用add(a, b),笔误写成ad(a, b)
}

将add.c编译成libadd.so,编译不报错,仅提示隐式函数声明警告,用ldd -r查看该so, 发现未定义符号ad。
在这里插入图片描述
$ ldd -r libadd.so
undefined symbol: ad (./libadd.so)

此时写一个main程序,调用libadd.so中的sum方法求三数之和

#include<stdio.h>
extern int sum(int, int, int);
int main() {
	printf("%d\n", sum(1, 2, 3));
	return 0;
}

编译main程序出错,错误原因在于编写add.c时将符号add错写成了ad,由于忽视隐式函数声明警告,导致该错误没有在编译add.c的时候及时发现。

$ gcc main.c -L. -ladd
./libadd.so: undefined reference to `ad’
collect2: error: ld returned 1 exit status

  • 对于用dlopen动态加载该so库的程序,如指定RTLD_NOW,dlopen立即失败;如指定RTLD_LAZY延迟绑定,则dlopen成功,但dlsym加载引用了未定义符号的函数(如sum函数)会出错,示例main程序如下:
#include<dlfcn.h>
#include<stdio.h>
#include<stdlib.h>
int main() {
	void *handle = dlopen("./libadd.so", RTLD_LAZY);
	if(handle == NULL) {
		fprintf(stderr, "%s\n", dlerror());
		exit(-1);
	}
	int (*add)(int, int);
	int (*sum)(int, int, int);

	add = dlsym(handle, "add");	// add方法正常执行
	printf("1 + 2 = %d\n", add(1, 2));

	sum = dlsym(handle, "sum");	// 出错,报未定义符号ad
	printf("1 + 2 + 3 = %d\n", sum(1, 2, 3));
	return 0;
}

$ gcc main.c -ldl

$ ./a.out

1 + 2 = 3

./a.out: symbol lookup error: ./libadd.so: undefined symbol: ad

虽然编译成功,libadd.so可以加载,add函数可以执行,但执行sum函数时报未定义符号错。如及时处理隐式函数声明警告,可以在编译add.c的时候就发现该问题。

注意事项:
  • 函数先声明再使用,包含必要的头文件。

  • 重视编译器的隐式函数声明警告, 可开启-Werror选项检查, 不要简单使用-Wno忽略该编译告警。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

pcj_888

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值