malloc(及其堂兄弟)返回的内存块是否初始化为零?

时间:2015-03-05 15:55:23

标签: c linux memory memory-management malloc

我编写了一个代码来测试,以测试Linux和Windows操作系统的内存管理。为了进一步测试,我继续检查malloc()返回的内存中存在哪些值。

正在返回的值都是0(零)。我已经阅读了malloc的手册页,在Windows和Linux上都进行了检查,但我 不能找到这种行为的原因 。根据联机帮助页

  

malloc()函数分配大小字节并返回指向已分配内存的指针。内存未初始化。

要清除内存段,必须手动使用memset()。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdbool.h>

int eat(long total,int chunk){
    long i;
    for(i=0;i<total;i+=chunk){
        short *buffer=malloc(sizeof(char)*chunk);     
        if(buffer==NULL){
            return -1;
        }
        printf("\nDATA=%d",*buffer);
        memset(buffer,0,chunk);
    }
    return 0;
}

int main(int argc, char *argv[]){
    int i,chunk=1024;
    long size=10000;
            printf("Got %ld bytes in chunks of %d...\n",size,chunk);
            if(eat(size,chunk)==0){
                printf("Done, press any key to free the memory\n");
                getchar();
            }else{
                printf("ERROR: Could not allocate the memory");
            }
        }

也许我错过了什么。 代码改编自here

编辑:已针对GCC特定输出回答here问题。我相信Windows操作系统也会遵循相同的程序。

6 个答案:

答案 0 :(得分:12)

malloc()返回的内存未初始化,这意味着它可能是任何内容。它可能是零,也可能不是; 未初始化&#39; 表示它可以是任何内容(包括零)。要获得有保证的归零页面,请使用calloc()

您看到归零页面(无论如何在Linux上)的原因是,如果应用程序请求新页面,这些页面将被操作系统归零(或者更准确地说,它们是已知零的固定页面的写入时复制图像作为全球零页面&#39;)。但是如果malloc()碰巧使用已经分配给应用程序的内存(此时已经被释放(而不是扩展堆)),您可能会看到非零数据。请注意,操作系统提供的页面归零是操作系统特定的特征(主要用于安全性,因此一个进程最终不会发生碰巧有来自另一个进程的数据的页面),并且不是C标准强制要求的。

您要求get_free_page get_free_page()归零页面:&#39; free_page_list需要一个参数,一个优先级。 ...需要一页mem_map,更新calloc()将页面归零并返回页面的实际地址。&#39; source另一篇文章解释得很好,并解释了为什么使用malloc()优于memset() + int n; char nonzero=0; char *buffer=malloc(sizeof(char)*chunk); if(buffer==NULL){ return -1; } for (n = 0; n<chunk; n++) nonzero = nonzero || buffer[n]; printf("\nDATA=%s\n",nonzero?"nonzero":"zero");

请注意,您不会将整个分配的块检查为零。你想要这样的东西(未经测试):

{{1}}

答案 1 :(得分:2)

你绝对正确; C语言标准无法保证这种行为。

您正在观察的内容可能只是机会(您只在每次分配中检查几个字节),或者它可能是您的操作系统和C运行时库如何分配内存的工件。 / p>

答案 2 :(得分:0)

这句话:

printf("\nDATA=%d",*buffer);

您只检查刚刚sizeof(short)编辑的第一个malloc()字节数(通常为两(2)个字节)。

此外,第一次你可以幸运地获得所有零,但是在你的程序执行(并使用)堆内存之后,内容 - 之后 - malloc()将是未定义的。

答案 3 :(得分:0)

内存分配函数:calloc()将返回指向“&new”区域的指针并将所有字节设置为零。

内存分配函数:realloc()将返回指向(可能是新的)区域的指针,并复制了旧区域中的字节。新区域将成为新区域的新区域。要求的长度

内存分配函数malloc将返回指向新区域的指针,但不会将字节设置为任何特定值

答案 4 :(得分:0)

  

返回的值都是0(零)。

但这并不能保证。这是因为你只是在运行你的程序。如果你使用malloc,随机填充和释放很多,你将开始注意到以前释放的内存正被重用,所以你将开始在malloc中获得非零块。

答案 5 :(得分:0)

是的,你是对的malloc()没有零值初始化。它随意地拉出它从堆中分配的内存量,这实际上意味着可能已经存储了任何内容。因此,您应该仅在您确定要将其设置为值的情况下使用malloc()。如果您打算开箱即用,那么您可能会得到一些可疑的结果(我已经多次亲身体验过这一点;您有时会使用来获得功能代码疯狂的输出)。

所以设置东西你没有用memset()将值设置为零。或者我的建议是使用calloc()。除malloc之外的Calloc会对值进行零初始化。据我所知,比malloc()和memset()的组合更快,另一方面,malloc单独比calloc更快。因此,尽量通过保持形式的记忆来找到问题最快的版本。

另见这篇文章:MPI matrix-vector-multiplication returns sometimes correct sometimes weird values。问题是另一个问题,但原因是相同的。