下面的一个简单的程序,带有 malloc 和 scanf 和 %s 来获取如下字符串,给了我一个我无法理解的输出。虽然我只"错误定位"了 5 个字节,但我的输入字符串超过了上述大小,但没有分段错误。scanf 是否覆盖了 malloc 分配?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
char * name;
int SZSTRING;
printf("Enter size of name :");
scanf("%d", &SZSTRING);
name = (char*) malloc ((SZSTRING + 1) * sizeof(char));
printf("Enter name :");
scanf("%s", name);
printf("len of 'name' : %dn",strlen(name));
printf("name final: "%s"n",name);
free(name);
return 0;
}
Output:
OptiPlex-380:~/gsa/compile$ gcc -o try try.c
OptiPlex-380:~/gsa/compile$ ./try
Enter size of name :4
Enter name :qwertyui
len of 'name' : 8
name final: "qwertyui"
我在这里注意到了一件事:与
//scanf("%s", name);
输出显示
len of 'name'= 0
和"错误定位"位置实际上被内存设置为 NULL。但是它的 calloc 而不是 malloc,它根据手册页将分配的字节初始化为 0???
它可能看起来"有效",但这只是因为你很幸运。当我在一个编译器上运行您的代码时,它在另一个编译器上"工作",由于堆损坏而崩溃。如果你想使用 scanf()
,最好的办法是允许 scanf() 为你分配内存:
scanf("%ms", &name); // compiled with -std=c99 this will allocate the correct amount
// of memory for you. You can use "%as" if you're using -std=c89
还要记住,scanf()
有一个返回值(它告诉您成功匹配和分配的输入项的数量),检查它以了解它是否有效非常重要。
虽然我们采用良好做法,但不应将返回值类型转换为 malloc()
另一种不使用scanf()
,是改用fgets()
:
fgets( name, SZSTRING, stdin);
它没有。但是,超过分配的缓冲区大小并不总是立即导致分段错误。有时区域会损坏,效果会在以后甚至永远不会显示。
这种情况可能会在没有段错误的情况下运行。在这种情况下,只是您正在使用一个您尚未声明的空间,从而损坏了一些可能由"某人"拥有的内存位置。