【问题标题】:Why malloc and sbrk returns address from seperate segments?为什么 malloc 和 sbrk 从单独的段返回地址?
【发布时间】:2019-10-08 15:00:33
【问题描述】:

我正在尝试实现了解动态内存分配是如何发生的。所以我想到了使用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) 不是连续的位置。

【问题讨论】:

  • 现代 POSIX 分配器通常使用mmap 进行分配,而不是sbrk
  • 顺便说一下,打印指针 (void *) 的正确printf 格式是"%p"

标签: c malloc sbrk


【解决方案1】:

假设你在 Linux 上运行,malloc()sbrk() 的内存位置差异较大的原因是 glibc malloc() 实现在内部使用 sbrk() 来获取功能这样的内存作为malloc()返回给调用者。例如,假设最初的内部 glibc 实现通过sbrk() 获得 32 MB 的堆内存,而从malloc() 返回的内存将在这个 32 MB 块中。如果你然后使用sbrk() 来获取内存,它将来自原始32 MB 块末尾新分配的内存,因此malloc()sbrk() 的地址会有所不同。

请注意,您不能安全地混合使用malloc()(和calloc()realloc() 等)和sbrk(),因为malloc() 的内部实现使用sbrk() 来获取它的内存通过malloc() 返回。每the Linux malloc() man page

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

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

【讨论】:

    【解决方案2】:

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

    C11 标准规定:

    7.22.3 Memory management functions

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

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

    【讨论】:

      猜你喜欢
      • 2013-04-08
      • 2021-08-29
      • 2012-02-27
      • 2011-03-07
      • 2014-01-22
      • 2016-03-18
      • 2017-10-08
      • 1970-01-01
      • 2020-11-07
      相关资源
      最近更新 更多