【问题标题】:Automatic memory allocation occurs at compile time or at run time in C?自动内存分配发生在 C 的编译时或运行时?
【发布时间】:2021-02-06 11:40:28
【问题描述】:

如果我们谈论静态内存分配,据说它是在编译时分配的,但实际上编译器只是处理这个内存分配,它实际上只是在程序开始时分配的。例如,编译器可能会在编译后的二进制文件中创建一个大的data 段,当程序加载到内存中时,程序的data 段内的地址将用作分配内存的位置。

如果我谈论自动内存分配,它是在控件进入新范围时分配的。现在我的疑问是,在这种情况下,编译器是否也会出现并将一些虚拟地址传递到编译后的二进制文件中,该地址后来成为运行时实际分配内存的地址,或者该内存仅在运行时分配,没有编译器的任何作用,就像动态内存的分配方式?

如果我有一些局部变量,比如:

int a = 10;

会有编译时分配还是运行时分配?

【问题讨论】:

  • 编译器可以优化掉那个变量(不分配内存),只为那个变量使用寄存器(不分配内存)或者生成指令来为其分配堆栈空间。

标签: c memory scope static auto


【解决方案1】:

自动分配发生在运行时,尽管它的本质是系统特定的。自动存储持续时间变量可能最终会出现在寄存器中、堆栈上或完全优化掉。

如果它们最终进入堆栈,编译器会为分配变量的函数创建一个局部范围偏移量。也就是说,变量可能被称为SP + 8 或类似的东西,其中 SP 是堆栈指针。当输入函数时,它又可以保存任何值 - 编译器或机器代码不知道或不关心这一点,这就是堆栈溢出存在的原因。

您可能会发现这很有用:What gets allocated on the stack and the heap?

【讨论】:

  • 如果我做对了,这意味着编译器将创建范围偏移,但它们的实际分配将仅在运行时完成?
  • @LocalHost 是的,它们通过特定的推送指令或作为堆栈帧的一部分进行分配,具体取决于 ISA 和 ABI。
【解决方案2】:

局部变量在存入内存时会被放入栈中。

通常,函数的总堆栈大小要求是在编译时计算的。 然后,当进入一个函数时,堆栈指针被向下调整为函数的整个堆栈大小——堆栈通常从高地址向低地址增长。

每个局部变量都在当前堆栈帧中分配了一个地址,并且它们通常使用内存访问指令进行访问,这些指令以当前堆栈指针的给定偏移量读取或写入内存。

但是,在优化的构建中,局部变量通常也保存在 CPU 寄存器中(只要有足够的可用寄存器),根本不必存储在内存中。这样做的目的是避免内存访问以加快程序速度。寄存器分配(编译器选择将哪些变量存储在寄存器中以及将哪个寄存器用于哪个变量)取决于编译器分析变量的生命周期及其使用量的大量黑魔法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-08-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-06
    • 1970-01-01
    相关资源
    最近更新 更多