Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 如何分配零内存?_C_Linux_Memory Management - Fatal编程技术网

C 如何分配零内存?

C 如何分配零内存?,c,linux,memory-management,C,Linux,Memory Management,据我所知,我必须在calloc和malloc之间做出选择,前者将分配零内存,后者可按需分配内存 是否有一个函数结合了这两个属性?可以直接调用mmap 如果可能的话,为什么calloc不这样做?如果您试图用malloc模拟calloc(即使用malloc但接收零内存),那么您可以使用memset: foo = (char*)malloc(BLOCK_SIZE); memset(foo,'\0',BLOCK_SIZE); 但是,这是一个坏主意(它比calloc慢,请参阅:),并且不会由于中所述的原

据我所知,我必须在
calloc
malloc
之间做出选择,前者将分配零内存,后者可按需分配内存

是否有一个函数结合了这两个属性?可以直接调用
mmap


如果可能的话,为什么
calloc
不这样做?

如果您试图用malloc模拟calloc(即使用malloc但接收零内存),那么您可以使用memset:

foo = (char*)malloc(BLOCK_SIZE);
memset(foo,'\0',BLOCK_SIZE);

但是,这是一个坏主意(它比calloc慢,请参阅:),并且不会由于中所述的原因导致您所指的“延迟分配”。

calloc
malloc
相同,只是,正如您所说,它将分配的内存归零,并且它接受两个参数-
(NumberOfElements,ElementSize)
。所以

malloc(size);
相当于

calloc(1, size);
除了后者提供零内存


您所说的“按需”分配内存是什么?

有几种机制可以从操作系统获取预调零内存:

mmap(2)
MAP\u匿名
标志强制将内容初始化为零

POSIX共享内存段也可以归零

  • shm\u open(3)
    为您提供文件描述符
  • ftruncate(2)
    将“文件”设置为所需的大小
  • mmap(2)
    将“文件”插入您的地址空间
内存预先归零:

   This volume of IEEE Std 1003.1-2001 specifies that memory
   objects have initial contents of zero when created. This is
   consistent with current behavior for both files and newly
   allocated memory. For those implementations that use physical
   memory, it would be possible that such implementations could
   simply use available memory and give it to the process
   uninitialized. This, however, is not consistent with standard
   behavior for the uninitialized data area, the stack, and of
   course, files. Finally, it is highly desirable to set the
   allocated memory to zero for security reasons. Thus,
   initializing memory objects to zero is required.
此内存似乎在使用时已归零:
mm/shmem.c
function
shmem\u zero\u setup()


calloc
在概念上与
malloc
相同,后面是内存区域的归零

我不明白你为什么认为malloc在做懒惰的分配。事实并非如此

好的,有些Linux系统有,但你不应该依赖它(它更像是一个设计缺陷,而不是一个特性,IMHO)。此外,大型内存区域的
calloc
通常由一些不需要额外清除该区域的调用来实现

如果您需要一些惰性的东西,您可以使用
MAP\u NORESERVE
,但要小心。

在Linux上(可能也有其他操作系统,但不确定),当您执行malloc时,您分配的是虚拟地址空间,而不是真实地址空间。当您读取或写入该虚拟地址空间时,内核将找到可用的内存页,并将它们映射到该虚拟地址空间(它们可能是交换的,也可能是易失性内存)。如果运行htop之类的工具,它将显示一些内存统计信息。这里要看的大内存是驻留内存和虚拟内存。常驻内存是进程实际拥有的内存量,虚拟内存是所有已请求内存的总和

因此,当您调用calloc时,它将像malloc一样分配内存。然后它将向整个地址空间写入零。这些写操作将导致内核分配真实地址空间并将其映射到虚拟地址空间

因此,记住这一点,malloc本身并不是懒惰的,而是内核是懒惰的,并且在需要之前不会为进程分配内存页


一般来说,如果您需要将内存归零,您必须先使用calloc之类的工具将其归零,或者您需要自己跟踪哪些内存块已归零。

感谢指向malloc+memset与calloc performanceGlibc的链接。
calloc
知道
mmap
已将其归零内存,所以其他声称
calloc
总是自己写零(弄脏页面)的答案是错误的。但幸运的是,gcc甚至尽可能将malloc+memset优化为
calloc
。glibc的
calloc
知道
mmap
中的内存已经归零。使用
calloc
的大型分配不会使系统开始交换,因为它不会弄脏页面。gcc甚至将
mmap
+
memset
优化为
calloc
。(相关:除了原始mmap之外,为什么没有对齐的
calloc
,它生成的指针不能传递到
free
)良好的
calloc
实现已经避免了弄脏从操作系统获得的已知为零的页面。看见如果您希望这种行为具有额外的对齐方式,您只需要自己执行,因为似乎没有类似于
calloc
的函数接受对齐参数。
/**
 * shmem_zero_setup - setup a shared anonymous mapping
 * @vma: the vma to be mmapped is prepared by do_mmap_pgoff
 */     
int shmem_zero_setup(struct vm_area_struct *vma)
{   
    struct file *file;
    loff_t size = vma->vm_end - vma->vm_start;

    file = shmem_file_setup("dev/zero", size, vma->vm_flags);
    if (IS_ERR(file))
        return PTR_ERR(file);

    if (vma->vm_file)
        fput(vma->vm_file);
    vma->vm_file = file;
    vma->vm_ops = &shmem_vm_ops;
    return 0;
}