查看这两个C代码:
char* char_pointer;
int* int_pointer;
char_pointer = (char*)malloc(5);
printf("location of char_pointer: %p\n", char_pointer);
int_pointer = (int*)malloc(10);
printf("location of int_pointer: %p\n", int_pointer);
free(char_pointer);
char_pointer = (char*)malloc(50);
printf("location of char_pointer: %p\n", char_pointer);
和
char* char_pointer;
int* int_pointer;
char_pointer = (char*)malloc(200);
printf("location of char_pointer: %p\n", char_pointer);
int_pointer = (int*)malloc(10);
printf("location of int_pointer: %p\n", int_pointer);
free(char_pointer);
char_pointer = (char*)malloc(50);
printf("location of char_pointer: %p\n", char_pointer);
输出结果为:
location of char_pointer: 0x23eb010
location of int_pointer: 0x23eb030
location of char_pointer: 0x23eb050
和
location of char_pointer: 0x1815010
location of int_pointer: 0x18150e0
location of char_pointer: 0x1815010
如您所见,在第一个程序中,它决定在char_pointer
之后(在我释放和重新分配之后)分配int_pointer
但在第二个程序中它决定分配char_pointer
来代替释放记忆0x1815010
。
程序之间的唯一区别是分配和释放的内存量。
所以,我的问题是:
分配地点的决定取决于什么? (OS,编译器或硬件)
如果分配的内存量“很大”,为什么“它”决定分配代替释放的内存?
P.S。我在this book
中已经阅读过此问题答案 0 :(得分:4)
这取决于很多因素,并且没有简单的描述来描述行为。每个C运行时库都以不同方式实现malloc()
- 如果您对它的工作原理感到好奇,您可以查看CRT的源代码。
以下是一些常用的malloc()
实现:
malloc
(description)malloc
ptmalloc
malloc
:如果安装了Visual Studio,则%PROGRAMFILES(X86)%\Microsoft Visual Studio <VERSION>\VC\crt\src\malloc.c
中可用大多数内存分配器工作的粗略方式是它们跟踪可用的内存区域。当一个请求进入分配内存时,他们会看到是否有一个至少与请求一样大的内存区域,如果是这样,就会分割内存,更新其内部数据结构以反映内存现在是分配,并返回相应的指针。如果没有足够的可用内存,分配器将要求操作系统提供更多虚拟内存地址空间(通常通过sbrk(2)
,mmap(2)
或VirtualAlloc
)。
因此,如果块被分配然后被释放,然后经常(但不总是)请求相同大小(或更小)的另一个请求,则返回相同或类似的指针作为第一个块。
如果请求的分配非常大,分配器可能决定跳过其内部块处理,而是直接从OS满足请求 - 当分配数百KB或更多时,通常更直接{{1或者mmap()
那个内存,而不是试图在内部空闲内存区域列表中找到一个空闲块。但并非所有分配器都这样做,而确切的转折点通常是可变的。