【问题标题】: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_alloc、calloc、malloc 和 realloc 函数未指定。

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

    【讨论】:

      猜你喜欢
      • 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
      相关资源
      最近更新 更多