日常工作开发经常会存在不规范使用 extern 的情况,比如下面示例代码
//fun.c
int fun(int a)
{
return a+1;
}
//main.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char const *argv[])
{
int ret = 0;
ret = fun(1);
printf("ret:%d\n", ret);
return 0;
}
编译选项建议默认放开 -Wall ,否则可能编译链接过程并不会报错,执行也没问题。
对于编译时提示的编译告警都应该进行处理解决,这样大部分的传参类型不匹配都能解决掉,避免可能存在的安全问题。
如上图所示,在进行编译链接的时候,报了如下错误:
main.c:8:11: warning: implicit declaration of function ‘fun’ is invalid in C99 [-Wimplicit-function-declaration] ret = fun(1);
而很多时候,开发人员基本会为了方便,直接在 main.c 文件进行 extern 引用声明
extern int fun(int a);
通过该方式进行编译链接就不会存在告警了,但这是会存在风险的。
如果 fun 接口的维护人员修改了该接口实现,比如增加了入参个数变成下面这样了
int fun(int a, int b)
{
return a+b+1;
}
但并没有去修改 extern 处的函数声明,你会发现程序编译链接并不会出现任何告警,但执行结果就和之前完全不一样了,更有可能,修改了函数的实现后会直接导致程序崩溃。
正确的做法 fun.c 需要新增外部可包含的头文件声明 fun.h,而 main.c 要调用 fun.c 里的函数接口,则需要包含 fun.h 头文件。
这里还有一点需要注意,即 fun.c 也同样需要包含 fun.h 头文件,否则如果开发人员只修改了 fun.c 里的函数声明,但因为没有包含 fun.h 头文件,那么程序编译链接仍旧是不会报错的,只有 fun.c 也同样包含 fun.h 才会发生报错。
所以最终实现应该如下:
//fun.h
int fun(int a, int b);
//fun.c
#include <stdio.h>
#include "fun.h"
int fun(int a, int b)
{
return a+b+1;
}
//main.c
#include <stdio.h>
#include "fun.h"
int main(int argc, char const *argv[])
{
int ret = 0;
ret = fun(1, 2);
printf("ret:%d\n", ret);
return 0;
}
只有这样当开发人员修改了 fun.c 里 fun 函数的接口声明时,各引用的地方都会报错被发现。