int main()
{
char *p;
p = (char* ) malloc(sizeof(char) * 0);
printf("Hello Enter the data without spaces :\n");
scanf("%s",p);
printf("The entered string is %s\n",p);
//puts(p);
}
在编译上面的代码并运行它时,程序能够读取字符串,即使我们为指针p分配了一个0字节的内存。
声明p = (char* ) malloc(0)
实际发生了什么?
答案 0 :(得分:12)
实现定义malloc()
将返回什么,但使用该指针是未定义的行为。未定义的行为意味着任何事情都可以从程序工作中完成,而不会出现故障,所有安全的投注都会关闭。
C99标准:
7.22.3内存管理功能
第1段:
如果请求的空间大小为零,则行为是实现定义的:返回空指针,或者行为就像大小是非零值一样,但返回的指针不应用于访问一个对象。
答案 1 :(得分:0)
除了Als评论 - 会发生什么:你在某处写入内存并从那里检索数据。因此,根据您的系统和操作系统类型,您会得到异常或只是一些未定义的行为
答案 2 :(得分:0)
出于好奇,我在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'
aaaaaaaaaaa之后有一个小字形,这就是我的终端代表一个无法显示的unicode字符。这是覆盖数据的典型特征:你不知道 会覆盖你的数据......这是未定义的行为,所以你很容易受到鼻子的攻击。</ p>
最重要的是,当您写入内存时,您没有为其分配空间(显式使用malloc或隐式使用数组),您正在玩火。迟早,你会覆盖记忆,给自己带来各种各样的悲伤。
这里的真正教训是 C不进行边界检查。它会愉快地让你写入你不拥有的记忆。你可以整天做。您的程序可能正常运行,也可能没有。它可能会崩溃,它可能会写回损坏的数据,或者它可能会工作,直到您扫描比测试时使用的字节多一个字节。它不在乎,所以你必须这样做。
malloc(0)
的情况只是this question的一个特例。