注:本课程参考文献《C安全编码标准》
欢迎关注我👆,收藏下次不迷路┗|`O′|┛ 嗷~~
目录
一.隐含函数声明
二.不安全代码
三.兼容修改方案
四.练习和答案
一.隐含函数声明
隐含函数声明不允许;每个函数必须在调用之前明确声明,在C90标准中,如果函数在没有明确原型的情况下调用,编译器会提供一个隐含的声明。
如果函数调用中带括号的参数列表之前的表达式只包含一个标识符,且这一标识符没有可见的声明,该标识符将隐含声明,就像函数调用最内部的代码块中出现extern int identifier();声明一样。
此声明指出,该函数能够接受任意数量和类型的参数,并返回一个整型(int)值。但是,为了符合当前的C语言标准,程序员在调用任何函数之前,都必须显式声明该函数的原型。遵循C语言标准的编译器可能会支持隐式函数声明,也可能不支持,但C语言标准规定,在遇到未声明就使用的函数时,兼容的实现应当发出诊断信息。
二.不安全代码
在探讨这个不兼容的代码示例时,若malloc()
函数没有被明确声明(无论是直接声明还是通过包含stdlib.h
头文件间接声明),仅遵循C90标准的编译器可能会默认将malloc()
隐式声明为返回int
类型的函数,即int malloc()
。如果目标平台的int
类型大小为32位,而指针类型的大小为64位,那么由malloc()
隐式声明所返回的32位整数值可能会导致指针被截断,因为实际上需要一个64位的整数值来正确表示指针。
#include <stddef.h>
/* #include <stdlib.h> is missing */
int main(void){
for (size_t i = 0;i < 100; ++i){
/* int malloc() assumed */
char *ptr = (char *)malloc(0x10000000);
*ptr = 'a';
}
return 0;
}
三.兼容修改方案
下面的相容解决方案在声明malloc()时包含了相应的头文件。
#include <stdlib.h>
int main(void){
for (size_t i = 0;i < 100; ++i){
char *ptr = (char *)malloc(0x10000000);
*ptr = 'a';
}
return 0;
}
四.练习和答案
案例:
某开发者在编写一个程序时,尝试调用printf
函数来输出一些信息,但他忘记包含stdio.h
头文件。按照C90标准,编译器可能会对printf
函数提供一个隐含的声明,假设它返回一个整型值并接受任意数量和类型的参数。然而,在现代C语言编程实践中,这种做法是不被推荐的,因为它可能导致未定义行为,特别是当编译器的默认行为与实际的函数声明不一致时。
代码示例:
#include <stddef.h>
/* #include <stdio.h> is missing */
int main(void) {
for (size_t i = 0; i < 5; ++i) {
printf("Iteration %zu\n", i);
}
return 0;
}
问题:
- 在上述代码中,如果
stdio.h
头文件没有被包含,编译器可能会如何处理printf
函数的调用? - 如果编译器的默认行为是将
printf
隐式声明为返回int
类型的函数,这可能导致什么问题?
答案:
- 如果
stdio.h
头文件没有被包含,按照C90标准,编译器可能会对printf
函数提供一个隐含的声明,即假设它返回一个整型值并接受任意数量和类型的参数。 - 如果编译器的默认行为是将
printf
隐式声明为返回int
类型的函数,而实际上printf
函数的正确声明是返回一个int
类型的值,但其参数是一个格式字符串和可变数量的参数,那么这种隐式声明可能会导致未定义行为。特别是在一些平台上,如果编译器对函数参数的传递方式做了特定的假设(比如通过寄存器或特定的内存布局),那么隐式声明的函数可能无法正确地接收或处理这些参数,从而导致程序崩溃或产生不正确的输出。
兼容修改方案:
为了解决这个问题,开发者应该在源文件中包含stdio.h
头文件,以确保printf
函数被正确地声明。
#include <stdio.h>
#include <stddef.h>
int main(void) {
for (size_t i = 0; i < 5; ++i) {
printf("Iteration %zu\n", i);
}
return 0;
}
这样,编译器就可以根据stdio.h
头文件中提供的printf
函数的正确声明来处理函数调用,从而避免未定义行为的发生。
非常感谢您花时间阅读我的博客,希望这些分享能为您带来启发和帮助。期待您的反馈与交流,让我们共同成长,再次感谢!
👇个人网站👇