Вопрос

Я читал о Siof из книги, и это привело пример:

//file1.cpp
extern int y;
int x=y+1;

//file2.cpp
extern int x;
int y=x+1;  

Теперь мой вопрос:
В приведенном выше кодексе произойдет после событий?

  1. Во время компиляции файла1.cpp, компилятор листья y, как оно, то есть не выделяет для него хранилище.
  2. Компилятор выделяет хранение для X, но не инициализирует его.
  3. Во время компиляции файла2.cpp, компилятор оставляет X, как оно, то есть не выделяет для него хранилище.
  4. Компилятор выделяет хранение для Y, но не инициализирует его.
  5. При связывании File1.o и file2.o теперь позволяют File2.O инициализирован первым, так что теперь:
    Х получает начальное значение 0? Или не инициализируется?
Это было полезно?

Решение

Шаги инициализации приведены в 3.6.2 «Инициализация не локальных объектов» стандарта C ++:

Шаг 1: x а также y являются нулевыми инициализированными до того, как происходит любая другая инициализация.

Шаг 2: x или y динамически инициализируется - который не указан стандартом. Эта переменная получит значение 1 Поскольку другая переменная будет иметь нулевой инициализированной.

Шаг 3: Другая переменная будет динамически инициализирована, получая значение 2.

Другие советы

Siof - это очень просто артефакт времени выполнения, компилятор и линкер не имеют большого отношения к этому. Рассмотрим функцию ATEXIT (), она регистрирует функции, которые будут называться на выходе программы. Многие реализации CRT имеют нечто подобное для инициализации программы, давайте назовем его Atinit ().

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

Вот где atinit () входит в игру. Общее реализация CRT проводит список указателей функции ATINIT и выполнить фрагменты инициализации, в порядке. Проблема в том порядке, в котором функции зарегистрированы в списке Atinit (). В то время как Atexit () имеет четко определенный порядок Lifo, и он неявно определяется по порядком, в котором кодовые вызовы ATEXIT (), таковы не в этом случае для функций ATINIT. Спецификация языка не требует заказа, в вашем коде ничего не может сделать, чтобы указать заказ. Siof является результатом.

Одним из возможных реализации является указание функции компилятора в отдельном разделе. Линкер объединяет их, создавая список Atinit. Если ваш компилятор делает то, что порядок инициализации будет определен по заказу, в котором вы связываете объектные файлы. Посмотрите на файл карты, вы должны увидеть раздел Atinit, если ваш компилятор делает это. Это не будет называться Atinit, но какое-то имя с «init», скорее всего. Взглянув на исходный код CRT, который звонит главным (), должен также дать понимание.

Весь смысл (и причина, по которой это называется «Fiasco»), состоит в том, что невозможно сказать с какой-либо уверенностью какие произойдет в том случае, как это. По сути, вы просите что-то невозможное (что два переменных каждый превышает другой). Поскольку они не могут этого сделать, то, что они сделают, открыт для некоторого вопроса - они могут производить 0/1 или 1/0 или 1/2 или 2/1 или, возможно, (лучшее дело) просто ошибка сообщение.

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

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

Я думаю, что наиболее вероятный сценарий будет:

  1. Пространство выделяется для переменных, и оба имеют значение 0.
  2. Одна переменная, скажем, X, инициализируется и устанавливается на значение 1.
  3. Другой, скажем, y, инициализируется и установлен на значение 2.

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top