Инициализируется ли глобальная память в C++?
-
09-06-2019 - |
Вопрос
Инициализируется ли глобальная память в C++?И если да, то как?
(Второе) уточнение:
Когда программа запускается, что находится в пространстве памяти, которое станет глобальной памятью до инициализации примитивов?Пытаюсь понять, обнулено ли оно, или фигня например.
Ситуация такова:можно ли установить одноэлементную ссылку - через instance()
вызов перед его инициализацией:
MySingleton* MySingleton::_instance = NULL;
и в результате получить два экземпляра синглтона?
См. мою викторину по C++ для нескольких экземпляров синглтона...
Решение
Да, глобальные примитивы инициализируются значением NULL.
Пример:
int x;
int main(int argc, char**argv)
{
assert(x == 0);
int y;
//assert(y == 0); <-- wrong can't assume this.
}
Вы не можете делать никаких предположений о классах, структурах, массивах, блоках памяти в куче...
Безопаснее всего всегда все инициализировать.
Другие советы
Из стандарта:
Объекты со статической продолжительностью хранения (3.7.1) должны быть инициализированы нулями (8.5) до того, как будет произведена любая другая инициализация.Нулевая инициализация и инициализация с постоянным выражением вместе называются статическая инициализация;вся остальная инициализация динамическая инициализация.Объекты типов POD [простые старые данные] (3.9) со статической продолжительностью хранения, инициализированные постоянными выражениями (5.19), должны быть инициализированы до того, как произойдет какая-либо динамическая инициализация.Объекты со статической длительностью хранения, определенные в области пространства имен в одной и той же единице трансляции и динамически инициализируемые, должны инициализироваться в том порядке, в котором их определение появляется в единице трансляции.[Примечание: 8.5.1 описывает порядок, в котором инициализируются элементы агрегата.Начальная определение локальных статических объектов описана в 6.7.
Так что да, глобальные переменные, которые имеют статическую продолжительность хранения, будут инициализированы.Глобалы, выделенные, например, в куче, конечно, не будут инициализироваться автоматически.
Выходец из встроенного мира...
Ваш код компилируется в три типа памяти:
1..данные:инициализированная память
2..текст:константы и код
3..bss:неинициализированная память (инициализируется значением 0 в C++, если не инициализирована явно)
Глобалы попадают в .data, если они инициализированы.В противном случае они помещаются в .bss и обнуляются в премейн-коде.
Переменные, объявленные со статической/глобальной областью видимости, всегда инициализируются, по крайней мере, в VC++.
При некоторых обстоятельствах действительно может быть разница в поведении между:
int x = 0;
int main() { ... }
и
int x;
int main() { ... }
Если вы используете общие сегменты данных, то VC++, по крайней мере, использует явную инициализацию вместе с #pragma data_seg
чтобы определить, должна ли конкретная переменная находиться в сегменте общих данных или в сегменте частных данных процесса.
Для большего удовольствия представьте, что произойдет, если у вас есть статический объект C++ с конструктором/деструктором, объявленным в общем сегменте данных.Конструктор/деструктор вызывается каждый раз, когда exe/dll присоединяется к сегменту данных, что почти наверняка не то, что вам нужно.
Подробнее в этом статья базы знаний