为什么 malloc 和 sbrk returns 地址来自不同的段?

Why malloc and sbrk returns address from seperate segments?

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

这是我的代码

#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) 不是连续的位置。

该标准不对存储 的连续性提供任何保证,即使对于连续调用 malloc 分配的 内存也是如此.因此,代码中对 malloc 的不同调用不需要产生连续的位置。

C11 标准规定:

7.22.3 Memory management functions

1. The order and contiguity of storage allocated by successive calls to the aligned_alloc, calloc, malloc, and realloc functions is unspecified.

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

假设您在 Linux 上 运行,malloc()sbrk() 的内存位置差异较大的原因是 glibc malloc() 实现在内部使用 sbrk() 来获取调用者 malloc() return 等功能的内存。例如,假设初始内部 glibc 实现通过 sbrk() 获得 32 MB 的堆内存,并且从 malloc() 编辑的内存 return 将位于这 32 MB 块中。如果您随后使用 sbrk() 获取内存,它将从原始 32 MB 块末尾新分配的内存中获取,因此来自 malloc()sbrk() 的地址将不同。

请注意,您不能安全地混合使用 malloc()(以及 calloc()realloc() 等)和 sbrk(),因为 malloc() 使用 sbrk() 通过 malloc() 获取它 return 的内存。每 the Linux malloc() man page:

Normally, malloc() allocates memory from the heap, and adjusts the size of the heap as required, using sbrk(2). When allocating blocks of memory larger than MMAP_THRESHOLD bytes, the glibc malloc() implementation allocates the memory as a private anonymous mapping using mmap(2). MMAP_THRESHOLD is 128 kB by default, but is adjustable using mallopt(3). Prior to Linux 4.7 allocations performed using mmap(2) were unaffected by the RLIMIT_DATA resource limit; since Linux 4.7, this limit is also enforced for allocations performed using mmap(2).

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