malloc(及其同类)返回的内存块是否初始化为零?

Is the memory chunk returned by malloc (and its cousins) initialized to Zero?

我写了一个代码来测试Linux和WindowsOS的内存管理压力测试。只是为了进一步测试,我继续检查内存中存在哪些值 return 由 malloc() 编辑。

return 的值都是 0(零)。 我已经阅读了 malloc 的手册页,检查了 Windows 和Linux,但我无法找到此行为的原因。根据联机帮助页

The malloc() function allocates size bytes and returns a pointer to the allocated memory. The memory is not initialized.

要清除内存段,必须手动使用 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 操作系统也会遵循相同的程序。

你完全正确; C 语言标准不保证此行为。

您观察到的可能只是偶然(您只检查了每个分配中的几个字节),或者它可能是您的 OS 和 C 运行时库分配内存的方式的产物.

malloc()返回的内存没有初始化,也就是说可能是任何东西。它可能为零,也可能不是; 'not initialized' 意味着它可以是任何东西(包括零)。要获得保证归零的页面,请使用 calloc().

您看到清零页面(无论如何在 Linux 上)的原因是,如果应用程序请求新页面,这些页面会被 OS 清零(或者更准确地说,它们是复制的-写入称为 'global zero page') 的固定零页图像。但是,如果 malloc() 碰巧使用了已分配给已释放(而不是扩展堆)的应用程序的内存,您很可能会看到非零数据。请注意 OS 提供的页面归零是一个 OS 特定特征(主要是为了安全,这样一个进程不会以恰好包含来自另一个进程的数据的页面结束),并且是C 标准未强制要求。

您要求 source for get_free_page zeroing the page: that says 'get_free_page() takes one parameter, a priority. ... It takes a page off of the free_page_list, updates mem_map, zeroes the page and returns the physical address of the page.' Here 的另一个 post 解释得很好,并且还解释了为什么使用 calloc()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");

用这个语句:

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

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

此外,第一次你可能很幸运得到全零,但在你的程序执行(和使用)堆内存之后,malloc() 之后的内容将是未定义的。

内存分配函数:calloc() 将return指向新区域的指针并将所有字节设置为零。

内存分配函数:realloc() 将 return 一个指向(可能是新的)区域的指针,并从旧区域复制字节。新区域将是 'new' 要求的长度

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

The values that are being return are all 0 (zero).

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

是的,您是对的 malloc() 不会对值进行零初始化。它任意提取它被告知从堆中分配的内存量,这实际上意味着其中可能已经存储了任何内容。因此,您应该只在您确定要将其设置为一个值的情况下使用 malloc()。如果你打算立即使用它进行算术运算,你可能会得到一些可疑的结果(我已经有过几次亲身经历;你将拥有 有时 [=19= 的功能代码]疯狂输出)。

因此,使用 memset() 将您未设置的值设置为零。或者我的建议是使用 calloc()。与 malloc 不同的是,Calloc 对值进行零初始化。据我所知,它比 malloc() 和 memset() 的组合更快,另一方面,单独的 malloc 比 calloc 快。因此,通过保持记忆形式,尝试在问题点找到最快的版本。

另请参阅此处 post:。问题是不同的,但原因是一样的。