出于好奇,我在 linux 上使用 gcc 测试了您的代码,它比我预期的要强大得多(毕竟,将数据写入长度为 0 的字符缓冲区是未定义的行为......我希望它会崩溃) .
这是我对您的代码的修改:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char *p;
p = malloc(sizeof(char)*0);
printf("Hello Enter some without spaces :\n");
scanf("%s",p);
char *q;
q = malloc(sizeof(char)*0);
printf("Hello Enter more data without spaces :\n");
scanf("%s",q);
printf("The first string is '%s'\n",p);
printf("The second string is '%s'\n",q);
}
我的第一个想法是,您可能会因为您只将数据读取到单个内存位置这一事实而节省 - 如果您使用两个缓冲区,第二个可能会覆盖第一个......所以我将代码分解为输入和输出部分:
Hello Enter some without spaces :
asdf
Hello Enter more data without spaces :
tutututu
The first string is 'asdf'
The second string is 'tutututu'
如果第一个缓冲区被覆盖,我们会看到
The first string is 'tutututu'
The second string is 'tutututu'
所以事实并非如此。[但这取决于您将多少数据打包到每个缓冲区中......见下文]
然后,我将大量数据粘贴到两个变量中:
perl -e 'print "c" x 5000000 . "\n" ' | xsel -i
(这将 4+ MB 的 'c' 放入复制缓冲区)。我将其粘贴到第一个和第二个 scanf 调用中。该程序在没有分段错误的情况下使用它。
即使我没有分段错误,第一个缓冲区确实被覆盖了。我说不出来,因为太多的数据飞到了屏幕上。这是一个数据较少的运行:
$ ./foo
Hello Enter some without spaces :
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Hello Enter more data without spaces :
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
The first string is 'aaaaaaaaaaaa'
The second string is 'ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc'
在 aaaaaaaaaaaa 之后有一个小字形,这就是我的终端如何表示它无法显示的 unicode 字符。这是典型的覆盖数据:你不知道什么会覆盖你的数据......这是未定义的行为,所以你很容易出现鼻恶魔。
底线是,当您写入尚未分配空间的内存时(显式使用 malloc 或隐式使用数组),您就是在玩火。迟早,你会覆盖记忆,给自己带来各种各样的悲伤。
这里真正的教训是C 不做边界检查。它会很高兴地让你写入你不拥有的内存。你可以整天这样做。您的程序可能会正确运行,也可能不会。它可能会崩溃,它可能会写回损坏的数据,或者它可能会工作,直到您扫描的字节比测试时使用的多一个字节。它不在乎,所以你必须这样做。
的情况只是这个问题malloc(0)
的一个特例。