我在uefi edk2 bios源中工作。我们在EDK2源中创建了一个相关的平台新软件包。我发现了我们添加的平台相关代码的一个奇怪问题。
当我进行源级别调试时,我注意到了C函数中的局部变量在使用GCC编译时不会在堆栈中创建。
使用Visual Studio编译时相同的UEFI代码,则C函数中的本地变量正在堆栈中创建。
我在模拟环境上执行此代码,在该环境中,我可以看到堆栈基础,所有细分寄存器,当前执行代码,内存等。
它是一个多核系统,但仅在Enabled
如果您阅读了C11语言规范,您会发现它永远不会提及堆栈或堆栈帧或将变量放在堆栈上。C中无需将自动变量放入任何形式的堆栈中。
程序如何存储自动变量(即在功能范围内定义的变量,但没有static
关键字)完全取决于编译器。在过去,大多数编译器在系统堆栈上创建了参数,返回地址和本地变量的空间。在现代,这已经失去了青睐,因为处理器通常有很多寄存器,并且如果可能的话,将本地变量和功能论证保持在寄存器中更有效。
编译器需要在堆栈上存储自动变量的原因只有两个原因:
有太多的变量和论点将它们全部放在寄存器中
该功能采用变量的地址(您不能有指向寄存器的指针)
因此,GCC可能会决定它不需要为您的变量创建堆栈空间,并且可以在寄存器中进行。Visual Studio C编译器曾经以微软忽视而臭名昭著,因此它可能与自动变量有关的现代想法可能并不那么最新。
另外,您会发现编译器通常会优化变量。如果您对变量不做任何有用的事情,则编译器可能会决定它根本不需要。例如,在以下代码
中int f()
{
int i;
for (i = 0 ; i < 10 ; ++i);
return 0;
}
循环是空的,因此编译器知道它可以将其扔掉,然后不需要变量,因此它也会丢弃。