为什么 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.
并且来自 malloc
和 sbrk
调用混合的地址也不需要是连续的。
假设您在 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()
来获取内存时,您可能会破坏进程的堆。
我正在尝试理解动态内存分配是如何发生的。所以我想到了使用 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
, andrealloc
functions is unspecified.
并且来自 malloc
和 sbrk
调用混合的地址也不需要是连续的。
假设您在 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, usingsbrk(2)
. When allocating blocks of memory larger thanMMAP_THRESHOLD
bytes, the glibcmalloc()
implementation allocates the memory as a private anonymous mapping usingmmap(2)
.MMAP_THRESHOLD
is 128 kB by default, but is adjustable usingmallopt(3)
. Prior to Linux 4.7 allocations performed usingmmap(2)
were unaffected by theRLIMIT_DATA
resource limit; since Linux 4.7, this limit is also enforced for allocations performed usingmmap(2)
.
当您在 Linux 上混合使用 malloc()
和 sbrk()
来获取内存时,您可能会破坏进程的堆。