calloc与malloc + memset完全相同吗?

时间:2013-11-03 09:57:27

标签: c linux linux-kernel glibc

在linux中,calloc与malloc + memset完全相同,还是取决于确切的linux /内核版本?

我特别感兴趣的是你是否可以使用比实际更多的内存来调用RAM(因为你可以使用更多RAM来实现内存,你只能写入它)。换句话说,calloc总是实际上写入你已经分配的内存,因为规范建议应该这样做。

4 个答案:

答案 0 :(得分:5)

当然,这取决于实现,但在现代Linux上,你可能会。最简单的方法是尝试它,但我基于以下逻辑说这个。

你可以malloc超过你拥有的内存(物理+虚拟),因为内核会延迟你的内存分配,直到你真正使用它为止。我相信,为了增加你的程序因内存限制而失败的机会,但这不是问题。

callocmalloc相同,但零会初始化内存。当您向Linux请求内存页面时,Linux已将其初始化为零。因此,如果calloc可以告诉它所要求的内存只是从内核请求的,那么它实际上不必将其初始化为零!由于它没有,因此无法访问该内存,因此它应该能够请求比实际更多的内存。

正如评论中提到的this answer提供了一个非常好的解释。

答案 1 :(得分:2)

calloc是否需要写入内存取决于它是否从已分配给进程的堆页中获得分配,还是必须请求内核将更多内存分配给进程(使用系统调用,例如sbrk()mmap())。当内核为进程分配新内存时,它总是先将其归零(通常使用VM优化,因此实际上不必写入页面)。但如果它重用之前分配的内存,则必须使用memset()将其归零。

答案 2 :(得分:1)

cited duplicate或此处未提及。 Linux使用虚拟内存,可以分配更多系统中物理可用的内存。只需在用户空间中执行calloc()malloc()的{​​{1}}的简单实现即可触及每个页面。

由于Linux通常以4k块的形式分配,所有memset()块都是相同的,最初读为零。也就是说,相同的4k内存块可以映射只读,整个calloc()空间只能占用大约calloc()。当程序写入size/4k * pointer_size + 4k空间时,会发生页面错误,Linux将分配一个新页面(4k)并恢复该程序。

这简称为copy-on-write COW calloc()通常会以相同的方式行事。对于小尺寸,the 'C' library将使用 binning 并与其他小尺寸分配共享4k页。

因此,通常涉及两个层次。

  1. Linux内核的进程内存管理。
  2. glibc 堆管理。
  3. 如果请求的内存大小很大并且需要为进程分配新的内存,那么上述大部分内容都适用(通过Linux的进程内存管理)。但是,如果请求的内存很小,那么它就像malloc()malloc()。在大的分配大小中,memset()在触及内存时会受到破坏,内核认为需要分配新页面。

答案 3 :(得分:0)

你不能malloc(3) ram比内核给你的进程malloc(3)更多。如果无法分配要分配的内存量,则malloc(3)将返回NULL。此外,malloc(3)memset(3)由您的c库(libc.so)定义,而不是您的内核。 Linux内核定义mmap(2)和其他低级内存分配函数,而不是*alloc(3)系列(不包括kalloc())。