-
В документации не нашёл (верю, что есть), но google подсказывает много мест, где скопирован один и то же текст про инициализацию переменных. В частности, про глобальные переменные там есть пункт:
> Global variables are always initialized to 0 etc as well;
Но вот вопрос: что будет с глобальными переменными типа record? все поля глобальной структуры проинициализируются нулями? или приведённая цитата относится только к переменным "не составных" типов (т.е. только к int, double и т.п.)? Или можно быть уверенным, что, например, вот в такой глобальной переменной первое поле осле старта приложения будет nil, а второе false?
var GlobVar = record obj: TObject; isInited: Boolean; end;
-
По идее неинициализированные переменные помещаются в сегмент BSS, который инициализируется нулями при загрузке программы загрузчиком ОС. Можно сделать Detailed-Segments Map File, чтобы убедиться, что Ваша запись туда попала.
-
А проверить сложно? Т.е. прочитать переменную.
-
В чём проблема проинициализировать переменные самому?
-
Не знаю, как сейчас, а в D7-WinXP мне пришлось инициализировать самому структуру с массивом - в массиве был мусор.
-
> KilkennyCat © (15.07.18 13:32) [4] > Не знаю, как сейчас, а в D7-WinXP мне пришлось инициализировать > самому структуру с массивом - в массиве был мусор.
Про массив - не верю, признаться. Очевидно, что строки и (динамические) массивы и т.п. "волшебные штуки" Delphi гарантированно инициализирует. Иначе бы ничего неработало. (Да и про это явно написано в там же, "по-умному" называются А, или вероятно речь не про динамический массив, а про статический как поле структуры? тогда да, тогда это показательно (мы про глоб. переменную, верно?)
-
> dmk © (15.07.18 13:12) [2] > А проверить сложно? Т.е. прочитать переменную.
undefined behavior? нет, не слышал
-
> Styx © (15.07.18 12:12) [1]
Мысль сама по себе клёвая, но мне боязно подкладывать такую мину. (сейчас-то я проверю, а что будет после смены компилятора, например? никто ж не вспомнит про такой хитровыпученный нюанс и не проверит)
-
> после смены компилятора а компилятор тут не причем, это система выделяет память под данные и зануляет выделенное. переменные в программе/для компилятора это всего лишь адреса в этой выделенной памяти. те. виндой если так понятнее (Styx - загрузчиком ОС). добавлю, на линуксе под вайном ловил глюки с неопределенным начальным значением глобальных переменных (давно, уже читал пофиксено, но все равно все нужное с тех пор инициализирую сам, не рассчитывая на систему). в винде такого не было никогда.
-
sniknik © (15.07.18 17:11) [8]
Это не единственный глюк в вайне.
KSergey © (15.07.18 11:39)
> Но вот вопрос: что будет с глобальными переменными типа > record? все поля глобальной структуры проинициализируются > нулями?
Все поля проинициализируюстся нулями.
-
> KSergey © (15.07.18 15:58) [5]
я не помню, динамический или статический был. вроде, именно динамический. И на самом деле, мусор совершенно не противоречит работе, с чего вдруг ничего бы не работало? Выделилась память, в памяти что-то было - вот и мусор. Заполнение памяти нулями иль чем-то иным (например, при прогоне через усб лучше FF) - рядовое явление после объявления массива. На эту тему как-то давно на встрече в Москве спорили, тож некоторые считали, что мусора не будет. Но я помню, тогда еще эксперимент проводил - объявлял максимально большой массив, смотрел его дамп и узнавал обрывки данных.
-
> kilkennycat © (16.07.18 00:55) [10] > я не помню, динамический или статический был. вроде, именно > динамический. И на самом деле, мусор совершенно не противоречит > работе, с чего вдруг ничего бы не работало?
Штука в том, что состояние динамического массива должно быть гарантировано корректным в любое время. А потому, если s: String; или a: array of integer; компилятор не проинициализирует нулями гарантированно - то первая же любая работа с ними приведёт к обращению в недоступную память. Ну, понятно же, что SetLength(aб 5) сначала должно освободить ранее выделенную под массив память, тут-то и произойдёт бабах
-
SetLength(a, 5) я хотел сказать
-
> компилятор не проинициализирует нулями гарантированно
я имею ввиду саму (внутреннюю) структуру массива, не значения элементов после того, как память выделили; значения элементов как раз остаются с мусором и это понятно и тут проблем нет.
-
Всем спасибо за обсуждение, я понял.
-
> KSergey © (16.07.18 08:30) [13]
ну да, всё верно.
-
> На эту тему как-то давно на встрече в Москве спорили, тож некоторые считали, что мусора не будет.
- заполнение нуля при увеличении размера через SetLength() - документировано...
System.DynArraySetLength: ...
// Set the new memory to all zero bits FillChar((PChar(p) + elSize * oldLength)^, elSize * (newLength - oldLength), 0); ...
про BSS уже говорили... Мусор будет при размещении на стеке, и может зависеть от реализации менеджера памяти для чистых SysGetMem/SysReallocMem()
-
> han_malign © (19.07.18 18:08) [16]
Прикольно, в самом деле есть такой кусок. Похоже парни решили не заморачиваться интеллектом в компиляторе, и, не разбираясь в фактически хранящихся данных в массиве, прописывают 0 в любом случае на всю новую память. (хотя это гарантированно надо лишь для случая, когда в массиве элементы имеют тип с волшебно управляемым менеджментом, например строки). Хотя чуть выше в этом же месте освобождают память (при уменьшении размера массива) вполне себе с интеллектом.
|