malloc的行为(0)

malloc的行为(0),c,pointers,C,Pointers,编译并运行上述代码后,程序能够读取字符串,即使我们为指针p分配了0字节的内存 语句p=(char*)malloc(0)中实际发生了什么?malloc()将返回什么是实现定义的,但使用该指针是未定义的行为。而未定义的行为意味着任何事情都可能发生,从程序正常运行到崩溃,所有的安全赌注都没有了 C99标准: 7.22.3内存管理功能 第1段: 如果请求的空间大小为零,则行为由实现定义:要么返回空指针,要么行为就好像大小是某个非零值,但返回的指针不应用于访问对象 除了Als注释——发生了什么:您将某处写

编译并运行上述代码后,程序能够读取字符串,即使我们为指针p分配了0字节的内存


语句
p=(char*)malloc(0)
中实际发生了什么?

malloc()将返回什么是实现定义的,但使用该指针是未定义的行为。而未定义的行为意味着任何事情都可能发生,从程序正常运行到崩溃,所有的安全赌注都没有了

C99标准:

7.22.3内存管理功能 第1段:

如果请求的空间大小为零,则行为由实现定义:要么返回空指针,要么行为就好像大小是某个非零值,但返回的指针不应用于访问对象


除了Als注释——发生了什么:您将某处写入内存并从中检索数据。因此,根据您的系统和操作系统类型,您会遇到异常或一些未定义的行为

出于好奇,我在linux上使用gcc测试了您的代码,它比我预期的要健壮得多(毕竟,将数据写入长度为0的字符缓冲区是未定义的行为……我预计它会崩溃)

以下是我对您的代码的修改:

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);
}
如果第一个缓冲区被覆盖,我们将看到

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'
(这会将4+MB的“c”放入复制缓冲区)。我将其粘贴到第一次和第二次scanf调用中。程序接受了它,没有出现分段错误

即使我没有分段错误,第一个缓冲区还是被覆盖了。我说不出来,因为太多的数据飞到了屏幕上。以下是数据较少的跑步:

perl -e 'print "c" x 5000000 . "\n" ' | xsel -i
aaaa后面有一个小字形,这就是我的终端如何表示它无法显示的unicode字符。这是典型的覆盖数据:您不知道什么将覆盖您的数据。。。这是一种未定义的行为,所以你很容易受到鼻魔的影响

底线是,当您写入尚未分配空间的内存(显式使用malloc或隐式使用数组)时,您是在玩火。迟早,你会改写记忆,给自己带来各种各样的悲伤

这里真正的教训是C不做边界检查。它会很高兴地让你写下你不拥有的记忆。你可以整天都这样做。您的程序可能运行正常,也可能运行不正常。它可能会崩溃,可能会写回损坏的数据,也可能会一直工作到您扫描的字节比测试时使用的多一个字节。它不在乎,所以你必须


malloc(0)
的情况仅仅是

离题的一个特例。。但这不是一个好的做法,投马洛克回报。。请看,C不能保护您避免过度运行分配给您的缓冲区-您需要小心不要这样做,否则您将践踏其他人的内存。Als所写内容的一个附录可能重复-未定义的行为包括“这次它做了我认为应该做的事。”下次可能会有所不同。在不同的操作系统上,它可能会有所不同。但请注意,只要您只调用一次,
malloc
,就可以调用
free
。当我们没有为指针分配任何内存时,在这种情况下,写入不存在的内存应该会导致分段错误,对吗?我也在linux上使用gcc,没有出现分段错误。我对malloc(0)的这种行为感到困惑@svKris我最好的猜测是,当运行malloc(0)时,堆中的某个地方会有一个指针。malloc不保留任何内存,因此您不能保证不会覆盖堆中其他位置的数据,但它(可能)不会在您身上留下错误。若你们试图写入一个未初始化的指针,你们将要写入谁知道什么内存地址,所以你们可能会seg错误。例如,处理方式取决于实现。@svKris根据上面引用的c99标准,malloc(0)可能返回null,也可能返回其他内容。写入空指针会给您一个seg错误,所以gcc显然不是这样做的。说真的,不应该期望它会崩溃。没有定义它应该崩溃。相反,@BartonChittenden向
NULL
写入“will segfault”也是一个错误的假设。它有未定义的行为,没有定义它必须崩溃。
perl -e 'print "c" x 5000000 . "\n" ' | xsel -i
$ ./foo
Hello Enter some without spaces :
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Hello Enter more data without spaces :
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
The first string is 'aaaaaaaaaaaa'
The second string is 'ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc'