c-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 memoryn");
                getchar();
            }else{
                printf("ERROR: Could not allocate the memory");
            }
        }

也许我错过了什么。代码是从这里改编的

编辑:GCC特定输出的问题已在此处得到解答。我相信Windows操作系统也会遵循同样的程序。

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

您看到归零页面(无论如何,在Linux上)的原因是,如果应用程序请求新页面,这些页面将由操作系统归零(或者更准确地说,它们是零的固定页面的写时复制映像,称为"全局零页面")。但是,如果malloc()碰巧使用了已经分配给应用程序的内存,而该内存后来被释放(而不是扩展堆),那么您很可能会看到非零数据。请注意,操作系统提供的页面归零是操作系统特有的特性(主要是为了安全起见,这样一个进程就不会出现碰巧有来自另一个进程的数据的页面),而不是C标准强制要求的。

您要求提供get_free_page清零页面的来源:即get_free_page()需要一个参数,一个优先级。。。它从free_page_list中删除一个页面,更新mem_map将页面清零并返回页面的物理地址。'这是另一篇很好地解释了它的文章,也解释了为什么使用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=%sn",nonzero?"nonzero":"zero");

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

你所观察到的可能只是偶然的(你在每次分配中只检查了几个字节),也可能是你的操作系统和C运行库如何分配内存的产物。

使用以下语句:

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

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

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

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

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

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

正在返回的值均为0(零)。

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

是的,malloc()不为零初始化值。它任意地从堆中提取它被要求分配的内存量,这本质上意味着可能已经有任何东西存储在其中。因此,您应该只使用malloc(),在您确定要将其设置为值的情况下。如果你要直接用它进行算术,你可能会得到一些可疑的结果(我已经亲身经历过好几次了;你会有有时疯狂输出的函数代码)。

所以用memset()将没有设置为零的东西设置为零。或者我的建议是使用calloc()。除malloc外,Calloc的初始化值为零。据我所知,它比malloc()和memset()的组合更快。另一方面,单独使用malloc比calloc更快。所以,试着通过保持你的记忆力来找到最快的版本

看看这篇文章:MPI矩阵向量乘法有时会返回正确的值,有时会返回奇怪的值。问题是不同的,但原因是一样的。

相关内容

  • 没有找到相关文章

最新更新