malloc的行为(0)

时间:2012-05-21 11:42:41

标签: c pointers

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)实际发生了什么?

3 个答案:

答案 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的一个特例。