c文件的局部变量没有在堆栈中创建,它的GCC编译代码,

时间:2017-03-08 11:08:34

标签: c gcc stack bios uefi

我在UEFI EDK2 Bios源工作。我们在EDK2源中创建了一个与平台相关的新包。我发现我们添加的平台相关代码存在一个奇怪的问题。

当我进行源代码级调试时,我注意到了 当使用GCC编译时,C函数中的局部变量不会在堆栈中创建。

使用visual studio编译相同的UEFI代码然后在C函数中创建局部变量将在堆栈中创建。

我在Simulation环境中执行此代码,我可以看到堆栈库,所有段寄存器,当前执行代码,内存等。

它是一个多核系统,但只启用了启动带处理器

1 个答案:

答案 0 :(得分:0)

如果您阅读C11语言规范,您会发现它从未提及堆栈或堆栈帧或将变量放在堆栈上。 C中没有要求将自动变量放入任何类型的堆栈中。

程序如何存储自动变量(即在函数范围内定义但没有static关键字的变量)完全取决于编译器。在过去,大多数编译器在系统堆栈上为参数,返回地址和局部变量创建了空间。在现代,这已经不再受欢迎,因为处理器通常具有大量寄存器,并且如果可能的话,将局部变量和函数参数保存在寄存器中会更有效。

编译器需要在堆栈上存储自动变量的原因只有两个:

  1. 有太多的变量和参数将它们全部放在寄存器中

  2. 该函数获取变量的地址(您不能指向寄存器)

  3. 因此,gcc可能会决定不需要为变量创建堆栈空间,而是将其放入寄存器中。 Visual Studio C编译器总是因为被微软忽视而臭名昭着,所以它可能不是关于自动变量的现代想法。

    此外,您会发现编译器通常会优化变量。如果你没有对你的变量做任何有用的事情,编译器可能会认为它根本不需要它。例如,在以下代码中

    int f()
    {
        int i;
    
        for (i = 0 ; i < 10 ; ++i);
        return 0;
    }
    

    循环是空的,因此编译器知道它可以抛弃它然后它不需要变量,因此它也会抛弃它。