2017-01-12 3 views
1

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

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

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    | 
    _______________________ 

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

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

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

+0

Это искусство ASCII должно быть четыре разных моментальных снимка стека? –

+0

@MartinBonner да – Darlyn

ответ

0

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

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

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

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

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

Смежные вопросы