Активация записи

Мне трудно понять запись активации (я прочитал несколько ответов об этом).

Предположим, у нас есть код

  int n( int a){
int b = a/2;
return a + b;
}

int main (){
int first   = 1;
int second  = n(first);
int third   = 3;
int fourth  = n(third);
return 0;
}

когда программа начнет выполняться, стек будет заполнен, например,

  | first |
__________| activation_record |
|   first           |
____________________| third             |
| activation_record |
| first             |
_____________________| activation_record1  |
|  third              |
| activation_record   |
|  first              |
_______________________

запись активации помещает статические локальные переменные, адрес функции, параметры функции и возвращаемое значение в свой стек, если я понимаю это так, что после выполнения записи активации (или функции вызываемого) запись активации заменяется ее возвращаемым значением. и его стек освобожден?

Также при одной и той же функции, вызываемой несколько раз, и наличии стека вызовов, который должен содержать место для возврата данных, будет ли та же самая Activation_record помещена в стек, или она создается каждый раз, когда вызывается функция? При всем остальном можно ли поместить запись активации в стек во время компиляции?

Спасибо за ответ

1

Решение

Вы получаете разные ответы, потому что возможны разные решения. Стандарт C ++ описывает только наблюдаемое поведение, а макеты стека не наблюдаемы.

В частности, современные компиляторы уменьшат вашу программу до int main() { return 0; } потому что только возвращаемое значение является наблюдаемым.

Если бы вы написали return fourth;современные компиляторы поняли бы, что fourth==4 и заменил программу на return 4,

Но давайте на минутку предположим, что этих оптимизаций не происходит, и у вас есть обычный x64-компилятор. Опять же, результаты будут другими: обычный ABI x64 передает аргументы функции и возвращает значения в регистрах ЦП, а не в стеке. Это не использует все регистры x64, поэтому локальные переменные могут также зайти в реестр.

Различные записи активации также будут перекрываться, так как они не используются одновременно. На самом деле это не оптимизация, а необходимость, потому что компилятор в целом не может определить, сколько вызовов будет сделано. Пример: for (char&c : string) { c = toupper(c); } ,

0

Другие решения

Других решений пока нет …