我能用的内存比我的';我已经分配了malloc(),为什么? GCC(Linux)和Visual C++快件的输出是“123456789”,这是否意味着当有空闲内存时,我实际上可以使用比我分配的代码“>代码”( > )更多的内容?

我能用的内存比我的';我已经分配了malloc(),为什么? GCC(Linux)和Visual C++快件的输出是“123456789”,这是否意味着当有空闲内存时,我实际上可以使用比我分配的代码“>代码”( > )更多的内容?,c,C,为什么malloc(0)不会导致运行时错误 谢谢。不。这意味着你的程序运行不正常。它会写入它不拥有的内存位置。否。这意味着您的程序运行不正常。它将写入它不拥有的内存位置。否。您将获得未定义的行为。这意味着任何事情都有可能发生,从它崩溃(耶)到它“工作”(boo),再到它重新格式化你的硬盘,并用文本文件填充它,上面写着“UB,UB,UB…”(wat) 不必担心之后会发生什么,因为这取决于你的编译器、平台、环境、一天中的时间、最喜欢的苏打水等等,所有这些东西都可以做任何他们想做的事情 更具体地说,使

为什么
malloc(0)
不会导致运行时错误


谢谢。

不。这意味着你的程序运行不正常。它会写入它不拥有的内存位置。

否。这意味着您的程序运行不正常。它将写入它不拥有的内存位置。

否。您将获得未定义的行为。这意味着任何事情都有可能发生,从它崩溃(耶)到它“工作”(boo),再到它重新格式化你的硬盘,并用文本文件填充它,上面写着“UB,UB,UB…”(wat)

不必担心之后会发生什么,因为这取决于你的编译器、平台、环境、一天中的时间、最喜欢的苏打水等等,所有这些东西都可以做任何他们想做的事情

更具体地说,使用未分配的内存是未定义的行为。从
malloc(1)
得到一个字节,就是这样

否。您将获得未定义的行为。这意味着任何事情都有可能发生,从它崩溃(耶)到它“工作”(boo),再到它重新格式化你的硬盘,并用文本文件填充它,上面写着“UB,UB,UB…”(wat)

不必担心之后会发生什么,因为这取决于你的编译器、平台、环境、一天中的时间、最喜欢的苏打水等等,所有这些东西都可以做任何他们想做的事情


更具体地说,使用未分配的内存是未定义的行为。从
malloc(1)
得到一个字节,就是这样

您会得到未定义的行为-任何事情都可能发生。不要这样做,也不要猜测它是否有效。也许它会破坏记忆,你不会马上看到它。仅访问分配的块大小内的内存。

您会得到未定义的行为-任何情况都可能发生。不要这样做,也不要猜测它是否有效。也许它会破坏记忆,你不会马上看到它。仅访问分配的块大小内的内存。

当您请求
malloc
获取1字节时,它可能会从操作系统获得1页(通常为4KB)。此页面将分配给调用进程,因此只要您不超出页面边界,就不会有任何问题

然而,请注意,这绝对是未定义的行为

考虑以下(假设的)示例,说明在使用
malloc
时可能发生的情况:

  • malloc(1)
  • 如果
    malloc
    内部内存不足,它将进一步询问操作系统。它通常会收到一个页面。假设它的大小为4KB,地址从0x1000开始
  • 您的呼叫返回给您要使用的地址0x1000。由于您要求输入1字节,因此,如果您仅使用地址0x1000,则这是已定义的行为
  • 由于操作系统刚刚为从地址0x1000开始的进程分配了4KB内存,因此,如果您从地址0x1000-0x1FF读/写了一些东西,操作系统不会抱怨。所以你可以很高兴地这样做,但这是未定义的行为
  • 假设你做了另一个
    malloc(1)
  • 现在
    malloc
    仍有一些内存,因此它不需要向操作系统请求更多内存。它可能会返回地址0x1001
  • 如果使用第一个
    malloc
    中给出的地址写入超过1个字节,则在使用第二个
    malloc
    中的地址时会遇到问题,因为您将覆盖数据

  • 因此,关键是您肯定会从malloc中获得1个字节,但
    malloc
    内部可能会为您的进程分配更多内存。

    当您要求
    malloc
    获得1个字节时,它可能会从操作系统中获得1页(通常为4KB)。此页面将分配给调用进程,因此只要您不超出页面边界,就不会有任何问题

    然而,请注意,这绝对是未定义的行为

    考虑以下(假设的)示例,说明在使用
    malloc
    时可能发生的情况:

  • malloc(1)
  • 如果
    malloc
    内部内存不足,它将进一步询问操作系统。它通常会收到一个页面。假设它的大小为4KB,地址从0x1000开始
  • 您的呼叫返回给您要使用的地址0x1000。由于您要求输入1字节,因此,如果您仅使用地址0x1000,则这是已定义的行为
  • 由于操作系统刚刚为从地址0x1000开始的进程分配了4KB内存,因此,如果您从地址0x1000-0x1FF读/写了一些东西,操作系统不会抱怨。所以你可以很高兴地这样做,但这是未定义的行为
  • 假设你做了另一个
    malloc(1)
  • 现在
    malloc
    仍有一些内存,因此它不需要向操作系统请求更多内存。它可能会返回地址0x1001
  • 如果使用第一个
    malloc
    中给出的地址写入超过1个字节,则在使用第二个
    malloc
    中的地址时会遇到问题,因为您将覆盖数据

  • 因此,关键是您肯定从malloc获得了1个字节,但是
    malloc
    内部可能有更多的内存分配给您处理。

    您在这方面很幸运。您正在向不属于您的位置写信,这会导致未定义的行为。

    您在那里很幸运。您正在写入不属于您的位置,这将导致未定义的行为。

    您可能被允许使用,直到内存达到某个程序内存或应用程序访问受保护内存时最有可能崩溃的其他点。

    您可能被允许使用,直到内存达到某个程序内存
    char *cp = (char *) malloc(1);
    strcpy(cp, "123456789");
    puts(cp);
    
     typedef long Align;    /* for alignment to long boundary */
       union header {         /* block header */
           struct {
               union header *ptr; /* next block if on free list */
               unsigned size;     /* size of this block */
           } s;
           Align x;           /* force alignment of blocks */
       };
       typedef union header Header;
    
       -----------------------------------------
       |        |     SIZE     |               |
       -----------------------------------------
         |        |
      points to   |-----address returned touser
       next free
       block
            -> a block returned by malloc 
    
    char* test = malloc(1);
    
     --------------------------------------------------------------
    | free memory  | memory in size allocated for user |           |
    ----------------------------------------------------------------
                                                                  0x100(assume address returned by malloc)
                                                                  test
    
    char* test = malloc(1);
    printf("memory allocated in bytes = %d\n",test[-1]);