【问题标题】:Does memory allocation and initialisation take place separatelty during compile time and runtime?内存分配和初始化是否在编译时和运行时分开进行?
【发布时间】:2019-05-31 14:56:45
【问题描述】:

当我们声明一个变量时,比如一个 int,我想知道在内存分配和初始化过程中涉及的步骤。还有一个指针

int x = 5;

现在在编译期间,4 字节被分配给整数 x。但是内存什么时候被值 5 填满呢?初始化是否发生在编译或运行时执行期间。 同样,考虑

int x = 5;
int* p = &x;

在这两行中,分配和初始化的过程是什么。

【问题讨论】:

    标签: memory memory-management runtime dynamic-memory-allocation compile-time


    【解决方案1】:

    变量初始化取决于变量的种类。全局或静态变量在编译时初始化,而自动变量在运行时完全管理。

    全局变量

    • 在编译时,所有全局变量的值都是已知的。这些值由编译器写入目标文件的特定部分。

    • 在链接时,会收集所有目标文件并确定每个变量的内存位置。这允许知道每个变量的地址,以防这些地址之一被分配给另一个变量。
      结果,会生成一个可执行文件,其中包含每个部分(文本、数据、rodata 等)内容的描述。在 data 或 rodata 部分,写入所有初始化的全局变量的值。

    • 在运行时,加载程序读取不同部分的描述并询问操作系统内存。然后它将所有部分的内容复制到各自的内存位置。
      这是使用在编译或链接时确定的值初始化变量的方式。
      唯一的例外是初始化为零(或未初始化)的变量。它们位于一个特殊的部分(通常称为 bss)。为了减小可执行文件的大小,这些零值不会写入可执行文件中。相反,在执行main() 之前,运行时过程会将 bss 部分的所有内容都设置为零。

    自动变量

    程序完全不同。在程序运行之前不知道这些变量的位置,唯一的方法是通过机器指令计算它们的值。

    所以编译器首先判断这些变量是在寄存器还是内存中,当进入函数时,第一条指令是为局部变量保留堆栈空间并初始化它们的值。这是通过常规机器指令完成的。

    如果值是另一个变量的地址(比如 y=&x),
    * 如果 x 是本地(自动)变量,则地址将通过写入 y 堆栈指针寄存器的内容和编译器确定的给定偏移量之和来计算
    * 如果 x 是全局变量或静态变量,则在链接时,一旦全局变量的地址已知,链接器就会修改编译器生成的指令,将正确的地址写入用于表示y 的寄存器或堆栈位置。

    【讨论】:

      【解决方案2】:

      在某些情况下无法在运行时定义: 如果 user_input == “是”: 我的变量 = 5 别的: my_var = 7

      但通常这取决于负责的编译器程序员已经实现的概念。如果您使用不同的编译器或不同的语言,那么情况可能会有所不同。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-02-05
        • 2021-02-13
        • 1970-01-01
        相关资源
        最近更新 更多