Локальная переменная файла AC не создается в стеке, ее скомпилированный код GCC,
Я работаю в UEFI EDK2 биос источник. Мы создали новый пакет, связанный с платформой, в источнике EDK2. Я обнаружил странную проблему с кодом, связанным с платформой, который мы добавили.
Когда я выполнял отладку на уровне исходного кода, я заметил, что локальная переменная в функции C не создается в стеке при ее компиляции с GCC.
Тот же код UEFI при компиляции с Visual Studio, затем локальная переменная в функции C создается в стеке.
Я выполняю этот код в среде моделирования, где я могу видеть базу стека, все регистры сегментов, текущий исполняемый код, память и т. Д.
Это многоядерная система, но включены только процессоры Boot Strap.
1 ответ
Если вы прочтете спецификацию языка C11, вы обнаружите, что в ней никогда не упоминается стек, кадры стека или помещение переменных в стек. В C нет необходимости помещать автоматические переменные в любой вид стека.
Как программа хранит автоматические переменные (то есть те, которые определены в области действия функции, но без static
Ключевое слово) полностью зависит от компилятора. В старые времена большинство компиляторов создавали пространство в системном стеке для аргументов, адреса возврата и локальных переменных. В наше время это перестало быть популярным, потому что процессоры обычно имеют много регистров, и более эффективно хранить локальные переменные и аргументы функций в регистрах, если это вообще возможно.
Есть только две причины, по которым компилятор должен хранить автоматическую переменную в стеке:
Слишком много переменных и аргументов, чтобы поместить их в регистры
Функция берет адрес переменной (у вас не может быть указателя на регистр)
Таким образом, gcc, вероятно, решает, что ему не нужно создавать пространство стека для вашей переменной, и оно заносится в регистр. Компилятор Visual Studio C всегда был печально известен тем, что им пренебрегали Microsoft, поэтому он, вероятно, не совсем в курсе современных представлений об автоматических переменных.
Кроме того, вы обнаружите, что компиляторы часто оптимизируют переменные. Если вы ничего не делаете с вашей переменной, компилятор может решить, что он вообще не нужен. Например, в следующем коде
int f()
{
int i;
for (i = 0 ; i < 10 ; ++i);
return 0;
}
Цикл пуст, поэтому компилятор знает, что он может его выбросить, и тогда ему не нужна переменная, поэтому он тоже его выбросит.