动态内存分配如何工作?
How does dynamic memory allocation work?
考虑以下代码:
int *p = malloc(4);
int *i = malloc(4);
现在,已经分配了一块内存(上述情况下为4字节),基地址存储在p
。
在int *i = malloc(4)
行分配内存时。
编译器如何知道这块内存已分配?
为什么它没有分配与 int *p = malloc(4)
分配的相同内存块?
当您在代码中使用像 malloc
这样的例程并编译 link 您的代码为可执行程序时,软件例程库也会 link 编辑到您的代码中.该库中的例程具有用于从操作系统请求内存的软件,用于将内存分成多个部分并在使用 malloc
请求时将其发出,并用于跟踪已发出的内容和已释放的内容free
.
因此,每当您编译一个非常小的程序时,您都会得到一个大型的附加软件库,人们已经开发了很多年。
编译器不负责知道谁拥有哪一块内存,也不负责不小心践踏之前分配的内存。这是操作系统的工作。编译器生成汇编代码,其中汇编代码进行适当的系统调用以从 OS 获取指向一块动态内存的指针。为了演示,这里有一个愚蠢的例子:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int* ptr = malloc(4);
free(ptr);
return 0;
}
现在编译该程序并 main
反汇编时,汇编代码如下所示:
0x0000000100000f50 <+0>: push %rbp
0x0000000100000f51 <+1>: mov %rsp,%rbp
0x0000000100000f54 <+4>: sub [=11=]x10,%rsp
0x0000000100000f58 <+8>: mov [=11=]x4,%eax
0x0000000100000f5d <+13>: mov %eax,%edi
0x0000000100000f5f <+15>: movl [=11=]x0,-0x4(%rbp)
0x0000000100000f66 <+22>: callq 0x100000f8a
0x0000000100000f6b <+27>: mov %rax,-0x10(%rbp)
0x0000000100000f6f <+31>: mov -0x10(%rbp),%rax
0x0000000100000f73 <+35>: mov %rax,%rdi
0x0000000100000f76 <+38>: callq 0x100000f84
0x0000000100000f7b <+43>: xor %eax,%eax
0x0000000100000f7d <+45>: add [=11=]x10,%rsp
0x0000000100000f81 <+49>: pop %rbp
0x0000000100000f82 <+50>: retq
注意 callq
行。编译器只是负责调用适当的系统调用来获取动态内存。
考虑以下代码:
int *p = malloc(4);
int *i = malloc(4);
现在,已经分配了一块内存(上述情况下为4字节),基地址存储在p
。
在int *i = malloc(4)
行分配内存时。
编译器如何知道这块内存已分配?
为什么它没有分配与 int *p = malloc(4)
分配的相同内存块?
当您在代码中使用像 malloc
这样的例程并编译 link 您的代码为可执行程序时,软件例程库也会 link 编辑到您的代码中.该库中的例程具有用于从操作系统请求内存的软件,用于将内存分成多个部分并在使用 malloc
请求时将其发出,并用于跟踪已发出的内容和已释放的内容free
.
因此,每当您编译一个非常小的程序时,您都会得到一个大型的附加软件库,人们已经开发了很多年。
编译器不负责知道谁拥有哪一块内存,也不负责不小心践踏之前分配的内存。这是操作系统的工作。编译器生成汇编代码,其中汇编代码进行适当的系统调用以从 OS 获取指向一块动态内存的指针。为了演示,这里有一个愚蠢的例子:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int* ptr = malloc(4);
free(ptr);
return 0;
}
现在编译该程序并 main
反汇编时,汇编代码如下所示:
0x0000000100000f50 <+0>: push %rbp
0x0000000100000f51 <+1>: mov %rsp,%rbp
0x0000000100000f54 <+4>: sub [=11=]x10,%rsp
0x0000000100000f58 <+8>: mov [=11=]x4,%eax
0x0000000100000f5d <+13>: mov %eax,%edi
0x0000000100000f5f <+15>: movl [=11=]x0,-0x4(%rbp)
0x0000000100000f66 <+22>: callq 0x100000f8a
0x0000000100000f6b <+27>: mov %rax,-0x10(%rbp)
0x0000000100000f6f <+31>: mov -0x10(%rbp),%rax
0x0000000100000f73 <+35>: mov %rax,%rdi
0x0000000100000f76 <+38>: callq 0x100000f84
0x0000000100000f7b <+43>: xor %eax,%eax
0x0000000100000f7d <+45>: add [=11=]x10,%rsp
0x0000000100000f81 <+49>: pop %rbp
0x0000000100000f82 <+50>: retq
注意 callq
行。编译器只是负责调用适当的系统调用来获取动态内存。