хранение статических переменных - PullRequest
2 голосов
/ 21 января 2011

В C, где статическая переменная хранится в памяти? Предположим, есть две статические переменные, одна локальная для функции, а другая глобальная. Как эта запись поддерживается в таблице символов? Пожалуйста, объясните.

Ответы [ 3 ]

13 голосов
/ 21 января 2011

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

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

Этот бит в скобках выше важен. Вне функции static не определяет продолжительность хранения переменной, как в функции. Он решает, видна ли переменная за пределами текущей единицы перевода. Все переменные вне функций имеют статическую длительность хранения.

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

Другими словами, именно компилятор определяет, на какую переменную вы ссылаетесь с именем.


Здесь вы можете увидеть пример того, как хранятся переменные. Рассмотрим следующую маленькую программу на C:

#include <stdio.h>
int var1;
static int var2;
int main (void) {
    int var3;
    static int var4;

    var1 = 111;
    var2 = 222;
    var3 = 333;
    var4 = 444;

    return 0;
}

Создается следующая сборка:

.file             "qq.c"
.comm             var1,4,4
.local            var2
.comm             var2,4,4
.text
.globl            main
.type             main, @function
main:
    pushl         %ebp
    movl          %esp, %ebp
    subl          $16, %esp
    movl          $111, var1
    movl          $222, var2
    movl          $333, -4(%ebp)
    movl          $444, var4.1705
    movl          $0, %eax
    leave
    ret
.size             main, .-main
.local            var4.1705
.comm             var4.1705,4,4
.ident            "GCC: (Ubuntu 4.4.3-4ubuntu5) 4.4.3"
.section          .note.GNU-stack,"",@progbits

И вы можете видеть, что var1, var2 и var4 (статические единицы хранения) имеют строку .comm, чтобы пометить их как общие записи, подлежащие консолидации компоновщиком.

Кроме того, var2, var3 и var4 (те, которые невидимы вне текущей единицы трансдляции) имеют строку .local, так что компоновщик не будет использовать их для удовлетворения неразрешенных внешних факторов. в другом объектном файле.

И, изучив вывод ld --verbose при связывании файла, вы можете увидеть, что все общие записи попадают в область .bss:

  .bss            :
  {
   *(.dynbss)
   *(.bss .bss.* .gnu.linkonce.b.*)
   *(COMMON)
   : : :
  }
1 голос
/ 21 января 2011

Невозможно обобщить для каждого компилятора, но именно так это чаще всего и делается.

Будет блок памяти, отведенный компоновщиком для переменных, которые инициализируются во время загрузки, но могут быть изменены во время выполнения. Все статические переменные будут размещены в этом блоке независимо от того, являются ли они локальными или глобальными.

0 голосов
/ 21 января 2011

Учитывая следующий источник:

static int a_static_var = 5;

void foo(void)
{
    static int a_static_var = 6;

    return;
}

Visual Studio компилирует переменную следующим образом (по крайней мере, в этом случае - детали будут различаться от компилятора к компилятору и зависят от параметров):

_DATA   SEGMENT
_a_static_var DD 05H
?a_static_var@?1??foo@@9@9 DD 06H           ; `foo'::`2'::a_static_var
_DATA   ENDS

Таким образом, обе статические переменные попадают в сегмент данных - у статики, которая ограничена функцией, ее имя искажено таким образом, что она не будет «совпадать» с аналогичной переменной и другой функцией или исходным файлом.

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

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