когда глобальные переменные выделяют свою память? - PullRequest
8 голосов
/ 28 июня 2011

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

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

У меня был map<RTTI, object*> objectPool, который содержит образцы каждого класса в моем коде, который я использовал для загрузки объектов из файла.Для создания этих примеров я использую некоторые глобальные переменные просто для того, чтобы представить экземпляр класса в objectPool.Но иногда эти примеры были инициализированы до самого ObjectPool.И это породило ошибку во время выполнения.

Чтобы исправить эту ошибку, я использовал задержанный инициализатор map<RTTI,object*>* lateInitializedObjectPool;.Теперь каждый экземпляр сначала проверяет, инициализирован ли objectPool, и инициализирует его, если нет, а затем приводит себя в пул объектов.Кажется, это работает нормально, но я беспокоюсь, если даже память, необходимая для указателя пула объектов, не зарезервирована до того, как другие классы начнут представляться, и это может вызвать нарушение доступа.

Ответы [ 3 ]

6 голосов
/ 28 июня 2011

Переменные, объявленные в области пространства имен (в отличие от классов или функций), имеют пространство для самих объектов (sizeof (ObjectType)), выделенное загрузчиком исполняемого файла (или DLL).Если объект является POD, который использует агрегатную инициализацию, то он обычно получает свои значения, если компоновщик записывает эти значения непосредственно в исполняемый файл, а загрузчик exe просто помещает все эти данные в память.Объекты, которые не используют агрегатную инициализацию, изначально обнуляют свои значения.

После всего этого, если какой-либо из этих объектов имеет конструкторы, эти конструкторы выполняются до того, как main будетзапустить.Таким образом, если какой-либо из этих конструкторов динамически выделяет память, то именно тогда они это и делают.После загрузки исполняемого файла, но до запуска main.

3 голосов
/ 28 июня 2011

Обычно для переменных используются отдельные области памяти:

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

Когда я говорю «отдельная область памяти»«Я имею в виду некоторую память, которую исполняющий загрузчик ОС организует для процесса, так же, как в стеке или куче, но отличается тем, что эти области имеют фиксированный заранее определенный размер.В UNIX упомянутая выше область памяти «все 0» широко известна как «BSS», а не инициализированная 0 область - как «данные» - подробности см. http://en.wikipedia.org/wiki/Data_segment.

1 голос
/ 28 июня 2011

C ++ имеет понятие «статическая продолжительность хранения».Это относится ко всем видам переменных, которые будут занимать фиксированное количество пространства во время выполнения программы.К ним относятся не только глобальные переменные, но также static переменные на уровне имен, класса и функции.

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

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