编译器如何为程序分配内存?
how does compiler allocate memory to a program?
假设我正在用 C 编写程序,例如:
Code: [1 global var, main(with local vars), 3 functions(with local vars)]
鉴于函数调用将在堆栈帧上进行,编译器如何一眼就知道要分配多少内存?
有没有遇到编译器出错导致程序内存不足的错误?还是编译器总是会分配精确或额外的内存?
是否就此与OS进行调解?还是它自己做决定? OS 会干预吗?
编辑: 我找到了一个很有帮助的答案:
- 全局变量以
.data
或.bss
结束。
- main 和函数最终在程序内存中,通常称为
.text
。
- 计算堆栈使用量绝不是编译器的责任。它所做的只是创建将 push/pop 变量放入堆栈的函数,但它不会为您计算一些最坏的情况。然而,编译器可能会努力通过使用 CPU 寄存器或函数内联来优化代码来尽量减少堆栈的使用。
Given that function calls will be made on a stack frame, how does the compiler know at one glance how much memory to allocate?
不知道。堆栈分配在 运行 时间内完成,程序员有责任确保程序不会 运行 超出堆栈内存。
Does it ever happen that the compiler went wrong and the program got out-of-memory error? Or will the compiler always allocate exact or extra memory?
编译器在您的示例中分配的所有内存都是全局变量的内存,它最终位于 data/bss 段中而不是堆栈中。 compiler/linker 知道它可以为 data/bss 使用多少 RAM,并希望在你 运行 内存不足时告诉你。
您通常应该注意三个内存位置。
全局变量和静态变量所在的数据段(和 BSS 段)。编译器可以在编译时知道所有全局变量和静态变量的大小,并告诉加载器在程序启动时分配内存。如果内存不足,程序将无法启动。
堆。使用 malloc 和类似函数的分配使用此段。如果没有足够的内存,标准库会尝试增加它,如果失败,malloc returns 一个 NULL 指针。
堆栈。当函数被调用时,局部变量和参数的space分配在这里,函数returns时释放。如果没有足够的内存,它会增长到最大大小(通常是可配置的)。如果它无法增长或已达到最大值,则会抛出堆栈溢出异常或信号(Unix 上为 SIGSEGV)。
编辑:当然,程序指令在其他段(文本)中,它的大小在编译时也是已知的,就像数据段一样。
假设我正在用 C 编写程序,例如:
Code: [1 global var, main(with local vars), 3 functions(with local vars)]
鉴于函数调用将在堆栈帧上进行,编译器如何一眼就知道要分配多少内存?
有没有遇到编译器出错导致程序内存不足的错误?还是编译器总是会分配精确或额外的内存?
是否就此与OS进行调解?还是它自己做决定? OS 会干预吗?
编辑: 我找到了一个很有帮助的答案:
- 全局变量以
.data
或.bss
结束。 - main 和函数最终在程序内存中,通常称为
.text
。 - 计算堆栈使用量绝不是编译器的责任。它所做的只是创建将 push/pop 变量放入堆栈的函数,但它不会为您计算一些最坏的情况。然而,编译器可能会努力通过使用 CPU 寄存器或函数内联来优化代码来尽量减少堆栈的使用。
Given that function calls will be made on a stack frame, how does the compiler know at one glance how much memory to allocate?
不知道。堆栈分配在 运行 时间内完成,程序员有责任确保程序不会 运行 超出堆栈内存。
Does it ever happen that the compiler went wrong and the program got out-of-memory error? Or will the compiler always allocate exact or extra memory?
编译器在您的示例中分配的所有内存都是全局变量的内存,它最终位于 data/bss 段中而不是堆栈中。 compiler/linker 知道它可以为 data/bss 使用多少 RAM,并希望在你 运行 内存不足时告诉你。
您通常应该注意三个内存位置。
全局变量和静态变量所在的数据段(和 BSS 段)。编译器可以在编译时知道所有全局变量和静态变量的大小,并告诉加载器在程序启动时分配内存。如果内存不足,程序将无法启动。
堆。使用 malloc 和类似函数的分配使用此段。如果没有足够的内存,标准库会尝试增加它,如果失败,malloc returns 一个 NULL 指针。
堆栈。当函数被调用时,局部变量和参数的space分配在这里,函数returns时释放。如果没有足够的内存,它会增长到最大大小(通常是可配置的)。如果它无法增长或已达到最大值,则会抛出堆栈溢出异常或信号(Unix 上为 SIGSEGV)。
编辑:当然,程序指令在其他段(文本)中,它的大小在编译时也是已知的,就像数据段一样。