为什么scanf在"int"的情况下给出最大值,但在超过限制的情况下在"char"的情况下崩溃程序?
#include<stdio.h>
main(){
int a;
char ch[10];
scanf("%d",&a);
printf("%d",a);
scanf("%s",ch);
printf("%s",ch);
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,它会崩溃你的程序,因为它scanf()有一个固有的不安全的字符串接口.它无法知道您的参数ch是一个足以容纳9个字符的字符串加上其终止nul的数组.因此,非常乐意继续从stdin数组末尾读取字符并将其存储在内存中.
如果你的程序崩溃,你真的很幸运.在最糟糕的情况下,攻击者使用精心设计的字符串来操纵堆栈的内容,以便控制您的计算机.这是缓冲区溢出攻击的一个示例.这听起来不太可能,但据记载,它已在很多场合发生.
仅用于数字,scanf通常足够安全,但它在处理输入错误方面不是很好.因此,通常使用类似于fgets()读取输入的东西(它具有控制溢出的缓冲区长度参数)并sscanf()从该缓冲区进行解析,随时测试其返回值以获得完整性通常是个好主意.
编辑:正如R的评论指出的那样,我夸大了scanf界面固有的危险.小心地在所有字符串上正确使用字段宽度说明符,scanf变得更安全.但是,您负责保证指定的宽度确实适合缓冲区.对于该示例,您应该编写,scanf("%9s",ch);因为您的缓冲区被声明为十个字节长,并且您需要空间来终止nul.
请注意,您还应该测试返回值scanf().它返回成功匹配的字段数,或者EOF是否发生I/O错误.例如,如果用户在预期数字时输入"abc",它可能返回0.