Когда происходит динамическая c инициализация изменчивой переменной stati c? - PullRequest
0 голосов
/ 27 января 2020

Во-первых, давайте посмотрим на стандарт (C ++ 14 [basi c .start.init] 3.6.3 / 4):

Определяется ли реализация Dynami c Инициализация нелокальной переменной с STATI c Срок хранения выполняется до первого оператора main. Если инициализация откладывается до некоторого момента времени после первого оператора main, это должно произойти до первого использования odr (3.2) любой функции или переменной, определенной в той же единице перевода, что и для инициализируемой переменной.

Спецификатор volatile означает, что переменная может быть изменена из внешнего источника. Однако, когда нет гарантии, когда она инициализируется, может случиться так, что переменная будет изменена извне, а затем произойдет динамическая инициализация c. Или это работает по-другому, когда ключевое слово volatile присутствует?

Вот пример того, о чем я говорю: в myfile.h

#ifndef MYFILE_H_
#define MYFILE_H_

int my_init ();

#endif /* MYFILE_H_ */

в myfile. cpp

#include <myfile.h>
#include <iostream>

int my_init () {
    std::cout << "init" << std::endl;
    return 1;
}

static volatile int my_var  __attribute__((unused)) = my_init();

в основном. cpp

#include <myfile.h>
#include <iostream>

int main() {
    std::cout << "main" << std::endl; 

    // Let's assume first odr-use of my_var or my_init happens down here, maybe 
    // in a function from another translation unit.

    return 0;
}

Просто представьте, что my_init - это функция, которая устанавливает my_var в допустимое состояние по умолчанию, на случай, если он не будет установлен внешне для другого действительное состояние. Следовательно, существует проблема, когда my_var сначала модифицируется извне, но затем устанавливается в состояние по умолчанию. Отсюда вопрос, когда инициализируется my_var. Как и в приведенной выше стандартной цитате, или volatile меняет игру?

1 Ответ

1 голос
/ 27 января 2020

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

Вы говорите: «можно изменить из внешнего источника». Но любая такая модификация была бы использованием odr переменной (фактически переменной), определенной в той же единице перевода.

Тем более что внешние источники не имеют доступа к переменной stati c в все, если вы не экспортируете адрес или не имеете функций для его изменения. Которые оба будут в одном и том же переводчике. Итак, еще раз, init происходит перед использованием.

Единственный случай, который я не вижу, это когда вы объявляете переменную volatile, потому что аппаратное обеспечение изменит ее вне контроля кода, как таймер. Но тогда вам лучше инициализировать оборудование вручную или знать, что делает ваша реализация. Порядок инициализации будет иметь значение так же, как и когда.

...