C文件的局部变量未在其GCC编译的代码堆栈中创建



我在uefi edk2 bios源中工作。我们在EDK2源中创建了一个相关的平台新软件包。我发现了我们添加的平台相关代码的一个奇怪问题。

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

使用Visual Studio编译时相同的UEFI代码,则C函数中的本地变量正在堆栈中创建。

我在模拟环境上执行此代码,在该环境中,我可以看到堆栈基础,所有细分寄存器,当前执行代码,内存等。

它是一个多核系统,但仅在Enabled

中启动带绑带处理器

如果您阅读了C11语言规范,您会发现它永远不会提及堆栈或堆栈帧或将变量放在堆栈上。C中无需将自动变量放入任何形式的堆栈中。

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

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

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

  2. 该功能采用变量的地址(您不能有指向寄存器的指针)

因此,GCC可能会决定它不需要为您的变量创建堆栈空间,并且可以在寄存器中进行。Visual Studio C编译器曾经以微软忽视而臭名昭著,因此它可能与自动变量有关的现代想法可能并不那么最新。

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

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

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

最新更新