请考虑以下代码:
int *p = malloc(4);
int *i = malloc(4);
现在,已分配了一块内存(在上述情况下为4个字节),基址存储在p
中。
在行int *i = malloc(4)
中分配内存时。
编译器如何知道这块内存已分配?
为什么不分配用int *p = malloc(4)
分配的同一块内存?
答案 0 :(得分:2)
当您在代码中使用malloc
等例程并编译并将代码链接到可执行程序时,软件例程库也会链接到您的代码中。该库中的例程具有用于从操作系统请求内存的软件,用于将该内存分成多个部分并在malloc
请求时将其分发出来,并用于跟踪已发布的内容以及已发布的内容free
。
因此,无论何时编译一个非常小的程序,你都会得到一个人们已经工作多年的大型附加软件库。
答案 1 :(得分:1)
编译器不负责知道谁拥有什么内存而不是意外地践踏先前分配的内存。这是操作系统的工作。编译器生成汇编代码,其中汇编代码进行适当的系统调用,以从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 $0x10,%rsp
0x0000000100000f58 <+8>: mov $0x4,%eax
0x0000000100000f5d <+13>: mov %eax,%edi
0x0000000100000f5f <+15>: movl $0x0,-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 $0x10,%rsp
0x0000000100000f81 <+49>: pop %rbp
0x0000000100000f82 <+50>: retq
注意callq
行。编译器负责调用适当的系统调用来获取动态内存。