Обратите внимание, что инициализация нуля, выполняемая ОС в качестве функции безопасности, обычно выполняется только при первом выделении памяти. Под этим я подразумеваю любой сегмент в разделах кучи, стека и данных. Секции стека и данных обычно имеют фиксированный размер и инициализируются при загрузке приложения в память.
Сегмент данных (содержащий статические / глобальные данные и код) обычно не используется повторно, хотя это может быть не так, если вы динамически загружаете код во время выполнения.
Память в сегменте стека постоянно используется повторно. Локальные переменные, фреймы стека функций и т. Д. - все они постоянно используются и используются повторно и не инициализируются каждый раз - только при первой загрузке приложения.
Однако, когда приложение отправляет запросы на кучи памяти, диспетчер памяти обычно инициализирует нулями сегменты памяти перед предоставлением запроса, но только для новых сегментов. Если вы делаете запрос на кучу памяти, и в сегменте, который уже был инициализирован, есть свободное место, инициализация не выполняется во второй раз. Поэтому нет гарантии, что, если этот конкретный сегмент памяти будет повторно использован вашим приложением, он снова будет инициализирован нулем.
Так, например, если вы выделяете Foo в куче, присваиваете его полю значение, удаляете экземпляр Foo, а затем создаете новый Foo в куче, есть вероятность, что новый Foo будет размещен в та же самая точная ячейка памяти, что и у старого Foo, и поэтому его поле будет изначально иметь то же значение, что и поле старого Foo.
Если подумать, это имеет смысл, поскольку ОС только инициализирует данные, чтобы предотвратить доступ одного приложения к данным из другого приложения. Существует меньший риск, позволяющий приложению получать доступ к своим собственным данным, поэтому по причинам производительности инициализация выполняется не каждый раз - только в первый раз, когда конкретный сегмент памяти становится доступным для использования приложением (в любом сегменте).
Иногда, когда вы запускаете приложение в режиме отладки, некоторые среды выполнения в режиме отладки инициализируют данные стека и кучи при каждом выделении (так что ваше поле Foo всегда будет инициализироваться). Однако разные среды выполнения отладки инициализируют данные разными значениями. Некоторые нули инициализируются, а некоторые инициализируются значением «маркер».
Суть в том, что никогда не используйте неинициализированные значения где-либо в вашем коде. Нет абсолютно никакой гарантии, что они будут инициализированы нулями. Кроме того, не забудьте прочитать ранее связанную статью, касающуюся паренов и инициализации по умолчанию против значения, так как это влияет на определение «неинициализированного» значения.