Где глобальные переменные находятся в записи активации для C? - PullRequest
0 голосов
/ 10 ноября 2019

В C каждая функция имеет запись активации, которая размещается в кадре стека. Локальные переменные размещаются в записи активации их собственной функции. Итак, как обстоят дела с глобальными переменными? Где они расположены?

Например,

#include <stdio.h>
    int a;

    void v()
    {a= 2;
    int b;
    b++;
    }

    main()
    {
    int f;
    printf("\n%d",a);
    v();
    }


-----Activation record----

-------------------
-------------------
activation record for main
-------------------
int f
-------------------
-------------------
activation record of v
--------------------
int a
--------------------
int b
--------------------
---------------

Где хранится переменная x в соответствии с логикой записи активации?

Ответы [ 2 ]

2 голосов
/ 10 ноября 2019

В C каждая функция имеет запись активации, которая размещается в кадре стека.

Нет. Тем не менее, это, как это обычно решается компилятором. По крайней мере, если вы не активировали никаких оптимизаций.

Во-первых, стандарт C вообще ничего не говорит о стеке. Таким образом, ответ на этот вопрос будет о том, как это обычно решается на практике.

И обычно они находятся в сегменте данных или сегменте bss. Типичный макет выглядит так:

Stack - Grows down towards the heap. Used for local variables.
-----
...
...
...
----
Heap - Grows up towards the stack. Used for dynamically allocated memory.
----
BSS - Uninitialized data. Used for uninitialized global and static variables.
----
Data - Initialized data. 
----
Text - Runnable code
1 голос
/ 10 ноября 2019

В C каждая функция имеет запись активации, которая размещена в кадре стека.

Неправильно , оптимизирующий компилятор может не иметьсделать это (и gcc -O3 -flto не будет, в Linux / x86-64 с недавним GCC ). Это будет встроенный некоторые функции. Некоторые локальные данные хранятся только в некоторых регистрах процессора (поэтому не имеют места в памяти). Прочитайте о распределении регистров , например, в Dragon Book или каком-либо другом учебнике о компиляторах. Помните о автоматических переменных . Также имейте в виду, что вам даже не нужен компьютер для запуска программы на C (хороший способ научить C - это играть в классе, как компьютер; вы можете запустить программу на C на бумаге карандашом).

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

Спецификация C11 не требует никакого стека вызовов. Проверьте, прочитав n1570 . Некоторые реализации не используют какой-либо стек вызовов (или записи активации). Помните, что crt0 вызывает ваши main.

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

. В Linux попробуйте cat /proc/self/maps, чтобы понять виртуальное адресное пространство процесса , в котором он работает. cat команда;смотрите proc (5)

Посмотрите код ассемблера, сгенерированный gcc -O2 -fverbose-asm -S, используя Linux. Прочитайте о вызове GCC .

См. Также этот ответ .

В Linux играйте с nm (1) , readelf (1) , objdump (1) в вашем исполняемом или объектном файле (в формате ELF ).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...