C语言隐式声明导致的死机问题
概述:
在一次开发工作中,同样代码同样的一个配置操作在32位平台正常运行,64位平台上会立马死机。编译也没有报任何错误和警告,查看代码也没有任何可疑之处,实在有些莫名。经过打印定位到死机位置是使用一个指针函数A返回的地址进行memcpy操作会立马死机,打印出指针地址,发现函数A内打印指针地址正常,而外部调用这个函数接收到的返回值指针地址高32位被截断了,所以使用该指针就会立马死机。
意外的解决:
在本项目中有一个同样类似的指针函数B,这个操作可以正常使用,对比发现,A函数和B函数的区别就是B函数在头文件中增加了声明,A函数缺少该部分声明代码,抱着试一试的态度就将A函数也在头文件中声明一下,重新编译后,同样操作就可以正常运行了。虽然解决了问题,但是原因还是没有明白,作为一个合格的程序猿,必然是要深究一下了。接下来就是重点啦,C语言函数的隐式声明。
死磕到底:
通过查阅资料,发现C语言有一个隐式函数声明,也就是说如果我没有声明这个函数,C语言自动使用默认的隐式声明,而C语言默认隐式声明返回值都是int。如下:
int A(); //C语言默认的隐式声明
int main()
{
char *p = A();
return 0;
}
单纯编译是没有任何问题的,只有链接的时候回去找A函数这个具体定义,而我们是定义过的,所以链接的时候也是可以找到的,所以没有任何问题,整个编译链接通过了。这样我们就可以理解为何高32位会被截断了。我们知道64位平台指针是八字节,int类型是4字节,所以我们实际得到的A函数的返回地址是一个四字节的int类型,这也就解释了为何我们高32位会被截断了。
具体C语言的隐式声明解释可以查看该博主的分析,很详细,这里我就不赘述了。
找到了截断原因,但是还有一个疑问,GCC编译器对于这种的是要报警告的,我在编译的过程中竟然毫无警告显示,why?
查阅资料发现,gcc编译的警告是可以屏蔽显示的,主要是这两个选项。
1,-w的意思是关闭编译时的警告,也就是编译后不显示任何warning,因为有时在编译之后编译器会显示一些例如数据转换之类的警告,这些警告是我们平时可以忽略的。
2,-Wall选项意思是编译后显示所有警告。
然后查找该部分编译的makefile文件,果不其然,被人加了-w选项给屏蔽了警告,真的是意想不到,意外之喜,雪上加霜,语无伦次,绝绝绝绝!
总结一下:
1,平时开发对于跨文件调用函数,函数一定要声明。
2,不要关闭编译警告,有警告解决,看不见就是不存在的思想请杜绝。毕竟在座的都是优秀的程序员,哈哈哈哈!
