статическая инициализация определенного пользователем типа в C ++ (Win64 / PC)

Я использую VS2012 Win64 / PC

Я знаю, что есть много информации о том, что является статической переменной, и о порядке инициализации, это идет немного дальше.

Представьте себе в 1 CPP следующие строки:

struct A
{
void* a;
size_t b;
};

static bool bMyBoolean = true;
static std::vector<A> myVector;

Гарантия здесь в том, что bMyBoolean инициализируется раньше myVector,
Они также оба инициализируются раньше main() вызывается.
Тем не мение, myVector имеет допустимое значение и адрес памяти, но инициализируется во время _initterm bMyboolean инициализируется ранее и не требует вызова инициализации во время initterm.

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

Немного контекста: когда я перегружаюсь malloc например, и конструктор вызывается для пользовательского типа, он перейдет в malloc, но некоторые из ваших статических данных здесь еще не готовы (это ожидается, так как статические переменные между единицами перевода не гарантированы), но это означает, что я могу получить доступ и изменить их безопасно, а затем они будут повторно инициализированы.

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

Если это так, как вы можете отслеживать ваши пользовательские типы, которые объявлены статическими?

2

Решение

Это потому, что стандарт C ++ различает три типа инициализации:

  • нулевой инициализации
  • постоянная инициализация
  • динамическая инициализация.

§ 3.6.2

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

    Постоянная инициализация выполняется:

    • если каждое полное выражение (включая неявные преобразования), которое появляется в инициализаторе ссылки со статическим или потоком
      продолжительность хранения является константным выражением и ссылка связана
      lvalue, обозначающему объект со статической продолжительностью хранения или
      временный
    • если объект со статической или потоковой длительностью хранения инициализируется вызовом конструктора, если конструктор является конструктором constexpr,
      если все аргументы конструктора являются константными выражениями (включая
      преобразования), и если после подстановки вызова функции каждый
      вызов конструктора и полное выражение в mem-инициализаторах и в
      инициализаторы скобок или равных для нестатических членов данных являются
      постоянное выражение
    • если объект со статическим или потоковым сроком хранения не инициализируется вызовом конструктора и если каждое полное выражение, которое
      появляется в его инициализаторе постоянное выражение.

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

Вы говорите о постоянной инициализации (части статической инициализации), и она не ограничена встроенными типами.

Ознакомьтесь с разделом 3.6.2 стандарта: «Инициализация нелокальных переменных» если вы хотите узнать больше.


[…] но это означает, что я могу получить доступ и изменить его безопасно, и тогда это будет повторно инициализировано.

Конечно, вы всегда можете изменить содержимое в определенной области памяти, если это позволяет ОС. Думайте об этом как о размещении нового — для такого объекта есть выделенная память, но конструктор вызывается, когда дело доходит до фазы инициализации. Так что оно инициализируется «на месте».

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

Нет. Нет прямой связи между типом переменной и ее местоположением. Локальные переменные помещаются в стек, динамически (распределяются через malloc()/new) живут внутри кучи, а статические размещаются внутри изображения (например, MyApp.exe). После выполнения приложения оно загружается в память, включая все объекты со статическим хранилищем, для которого память зарезервирована на этом этапе. Вы можете считать такие объекты действительными до тех пор, пока main() бежит.

2

Другие решения

У вас есть четыре вопроса в вашем посте. Тем не менее, я догадываюсь, что ваша главная задача состоит в том, чтобы государства некоторых из static объекты модифицируются malloc до того, как эти объекты будут инициализированы средой выполнения.

Лучше не полагаться на порядок инициализации глобального static переменные.

Если malloc необходимо изменить некоторые static данные, лучше обеспечить доступ к этим данным через функцию.

Вместо:

static std::vector<A> myVector;

использование

static std::vector<A>& getVector()
{
static std::vector<A> myVector;
return myVector;
}

Если ты это сделаешь, myVector гарантированно инициализируется, когда функция возвращается.

1

bMyBoolean а также myVector оба живут в статическом хранилище, внося в общей сложности sizeof(bool) + sizeof(std::vector<A>) байт. Статическое хранилище находится в самом файле изображения, скажем app.exe, Когда вы выполняете app.exeWindows загружает (отображает) файл образа в адрес виртуальной памяти, созданный для нового процесса, и именно тогда изначально «мертвое» статическое хранилище становится живым. Система позже запускает код в app.exe, который включает в себя вызов конструктора std::vector<A> на myVector, То есть на статическом хранилище myVector, Помните this указатель? this указатель, переданный в конструктор, будет указывать на статическое хранилище myVector, Память, выделенная конструктором, становится динамической и находится в куче. Указатель на это динамическое хранилище хранится в статическом хранилище myVector,

Я предлагаю вам прочитать больше о ссылках и загрузке.

0
По вопросам рекламы [email protected]