【发布时间】:2014-06-06 03:01:48
【问题描述】:
为了使这个问题简短(不检查 null 等),以下内容被缩写。
program1.c
main()
{
char *aString = calloc(10, sizeof(char));
printf("Enter string: ");
scanf("%s", aString);
printf("You typed in %s\n", aString);
}
program2.c
main()
{
char aString[10];
printf("Enter string: ");
scanf("%s", aString);
printf("You typed in %s\n", aString);
}
program1.c 将让我看似永远输入字符。我已经输入了 2000 多个字符,程序将毫无错误地执行,尽管这是“未定义的行为”。
program2.c 会让我输入超过 10 个字符,但如果接近 30 或 40 个字符,它会给我一个分段错误。
现在我对课堂和其他教程的有限理解告诉我,这两个程序在引擎盖下都在做同样的事情 --- 留出一块内存,打算成为长度为 10 的字符数组。但似乎program2.c 的实现提供了一定程度的安全性。或者,当您超过授予的内存空间时,分段错误错误是完全随机的,而我只是碰巧用 program2.c 得到它,只是因为我的计算机现在处于这种状态?
program1.c 和program2.c 有什么区别,哪个是输入字符串“更安全”的方法?我知道还有其他方法可能更好,但我很好奇这两种方法之间的比较。
【问题讨论】:
-
他们并没有在后台做同样的事情,因为静态或动态分配的内存不在同一个地方(分别是堆栈与堆)。更安全地使用
fgets来限制输入的字符串的大小。 -
它们都不安全:它不崩溃并不意味着它是安全的。您可以参考臭名昭著的“heartbleed”错误。
-
一些观察:main的原型是
int main(int,char**)或int main(void)。sizeof(char)是根据定义 1。您可以考虑使用"%9s"来避免char[10]上的缓冲区溢出。 -
让我猜你可以用 prog 1 输入 4095-4 个字符。 Calloc() 将在现代系统上为进程提供一个完整的内存页面,这些页面将被后续 [mc ]allocs,通常按升序排列。只有使用特殊的调试库,您的指针才能位于该页面的末尾,以便立即覆盖段错误,而不是破坏稍后分配的内存中的数据。
-
此代码与使用
gets一样安全……出于某种原因,人们会跳过gets帖子,但对scanf("%s"帖子的反应不同
标签: c arrays string memory segmentation-fault