c语言 - 为什么 malloc 和 sbrk 从单独的段返回地址?



我正在尝试实现了解动态内存分配是如何发生的。因此,我想使用系统调用实现自己的mallocsbrk()。 我的问题是当我尝试分配动态内存时,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)不是连续的位置。

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

请注意,您不能安全地混合使用malloc()(以及calloc()realloc()等)和sbrk(),因为malloc()的内部实现使用sbrk()来获取它通过malloc()返回的内存。 根据 Linuxmalloc()手册页:

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

当您在 Linux 上混合malloc()sbrk()以获取内存时,您可能会损坏进程的堆。

该标准不保证存储的连续性,即使是通过连续调用malloc分配的内存因此,代码中对malloc的不同调用不需要产生连续的位置。

C11标准规定:

7.22.3 内存管理功能

1. 通过连续调用aligned_alloccallocmallocrealloc函数未指定。

来自mallocsbrk呼叫混合的地址也不必是连续的。

相关内容

  • 没有找到相关文章

最新更新