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:。问题是不同的,但原因是一样的。
我写了一个代码来测试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: