为什么malloc和sbrk从不同的段返回地址?

时间:2019-05-22 07:26:56

标签: c malloc sbrk

我正在尝试了解动态内存分配是如何发生的。因此,我想到了使用sbrk()系统调用来实现自己的malloc。 我的问题是当我尝试分配动态内存时,sbrk()和malloc()返回不连续的不同地址。

这是我的代码

#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>

int main(int argc, char** argv)
{
    printf("\nsbrk(0) %llu ",(unsigned long long)sbrk(0));
    printf("\nmalloc(8) %llu ",(unsigned long long)malloc(8));
    printf("\nmalloc(8) %llu ",(unsigned long long)malloc(8));
    printf("\nsbrk(8) %llu ",(unsigned long long)sbrk(8));
    printf("\nmalloc(8) %llu ",(unsigned long long)malloc(8));
    printf("\nmalloc(8) %llu ",(unsigned long long)malloc(8));  
    printf("\n");
    return 0;
}

以上代码的输出为

sbrk(0) 30306304 
malloc(8) 30306320 
malloc(8) 30306352 
sbrk(8) 30441472 
malloc(8) 30306384 
malloc(8) 30306416 

谁能解释为什么sbrk(8)不是连续的位置。

2 个答案:

答案 0 :(得分:1)

该标准不能保证连续调用malloc所分配的存储 的连续性。因此,在代码中对malloc的不同调用无需产生连续的位置。

C11标准规定:

  

7.22.3 Memory management functions

     

1.由连续调用分配给存储区的顺序和连续性   未指定aligned_alloccallocmallocrealloc函数。

并且mallocsbrk调用混合产生的地址也不必是连续的。

答案 1 :(得分:0)

假设您正在Linux上运行,则malloc()sbrk()的内存在位置上有较大差异的原因是glibc malloc()实现使用了sbrk()在内部获取诸如malloc()之类的功能的内存返回给调用方。例如,假设初始内部glibc实现通过sbrk()获得32 MB的堆内存,并且从malloc()返回的内存将位于这32 MB块中。如果然后使用sbrk()获取内存,则它将来自原始32 MB块末尾新分配的内存,因此malloc()sbrk()的地址将有所不同。

请注意,由于{{1}的内部实现,您不能安全地混合使用malloc()(和calloc()realloc()等)和sbrk() }使用malloc()获取通过sbrk()返回的内存。根据{{​​3}}:

  

通常,malloc()从堆中分配内存,并调整          使用malloc()根据需要调整堆大小。分配块时          大于sbrk(2)个字节的内存,glibc MMAP_THRESHOLD          实现将内存分配为私有匿名映射          使用malloc()mmap(2)默认为128 kB,但          可使用MMAP_THRESHOLD进行调整。在Linux 4.7之前的分配          使用mallopt(3)执行的操作不受mmap(2)资源的影响          限制;从Linux 4.7开始,此限制也适用于分配          使用RLIMIT_DATA执行。

在Linux上混合使用mmap(2)malloc()以获得内存时,很可能会破坏进程的堆。