该死的c语言的隐式函数声明法则

来源:互联网 发布:linux 命令行 网页显示 编辑:程序博客网 时间:2024/05/22 02:11

在a.c文件里c函数的原型为:
char* function();

在另外的b.c文件里没有引用a.c对应的头文件,即没有function的函数原型声明,直接调用此上面的c函数:
char* ret = function();

编译没有什么问题,但是run的时候就发现程序在上述调用的位置crash掉了。用gdb跟踪发现调用后ret的值如下:
$2 = 0xfffffffff7fcf6f8 <Address 0xfffffffff7fcf6f8 out of bounds>

即function()函数返回的地址为非法的地址,而跟踪到function函数里面可知,它返回的值是一个类似于0xfffff7fcf6f8这样的合法值的。
为什么一到function函数的外面就是变成了0xfffffffff7fcf6f8这样的非法值呢?而且这个地址是在function内部的返回值0xfffff7fcf6f8的基础上补了两个全f字节,即不全了八个字节。

调试了一天也没有发现什么原因,这么稀奇的错误以前还真是从来没有碰到过,急死了!最后google了一下,有人提议碰到这种crash的问题,可以加-Wall来看下warning信息,crash出应该有对应的warning信息。于是乎,修改Makefile,加上警告信息。果然发现了warning信息,warning: assignment makes pointer from integer without a cast。

再根据此warning信息google了一把,发现然来c语言里面,使用之前没有声明的函数编译器都认为是隐式声明的函数,编译器会将所有隐式声明的函数的返回值类型都认定为int。然来问题在这里啊,对c语言用的不多,确实不知道还有这么一神奇的规则呀!function()返回的地址被编译器强制转换成int类型了,而64位OS上int为8个字接,所以function内部的返回值0xfffff7fcf6f8被补了两个全f字节变成了8个字节,故地址越界了。

从C99开始,废除了这条隐式函数声明法则,它会给出与c99之前版本不同的warning: implicit declaration of function。

所以呀,在c语言里面开来还是要学习c++的编程习惯,使用函数之前一定要声明。不然,即使编译能通过,运行时也可能会出一些莫名其妙的问题。
2 0
原创粉丝点击