Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2009.08.30;
Скачать: CL | DM;

Вниз

Насколько адекватен SizeOf   Найти похожие ветки 

 
Sha ©   (2008-06-05 23:12) [40]

> просто так   (05.06.08 22:39) [37]
> в d7 разбирался с выравниванием, сложного ниче небыло

а кому тут сложно?
нам мозги не заморочить даже примером из [32]

> Плохиш ©   (05.06.08 23:00) [39]
> Вообщв-то, в следующих букавках приводиться пример, почему запись T9 имеет размер 16 байт

Нет, не приводится. Там пишут про следующее поле C:
> The compiler pads the structure with unused bytes to ensure that C appears on a quadword boundary.
а в моем примере нету следующего поля (3-его)

>  Хотите верить в чудеса,
а это зачем?


 
Плохиш ©   (2008-06-05 23:19) [41]


> Нет, не приводится. Там пишут про следующее поле C:
> > The compiler pads the structure with unused bytes to ensure
> that C appears on a quadword boundary.
> а в моем примере нету следующего поля (3-его)

В твоём примере вместо этих 2х полей, одно размером 8 байт и на столько же сдвинуто следующее поле однобайтное, т.е. выравнено по восьмому байту. Или я не прав?


 
Sha ©   (2008-06-05 23:27) [42]

> Плохиш ©   (05.06.08 23:19) [41]

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


 
Плохиш ©   (2008-06-05 23:59) [43]


> Sha ©   (05.06.08 23:27) [42]


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

Я этой фразы честно сказать не понял, а в справке по bds2006 для Record Types написано, что выравнивание в записях производиться по the largest alignment of the fields in the record

> 2. При перекомпиляции проекта в после изменения атрибута
> packed в каком-либо модуле Борланд забывает перекомпилировать
> зависимые от него модули.

Значит эти модули не попадают под условия перекомпиляции, которые описаны в справке, в частности к D7.


 
Anatoly Podgoretsky ©   (2008-06-06 00:03) [44]

> Sha  (05.06.2008 23:27:42)  [42]

Ранее вроде так и былоо, но потом они стали мудрить с выравниваниями и возможно с размерами, что упростить себе жизнь.


 
Sha ©   (2008-06-06 00:45) [45]

> Плохиш ©   (05.06.08 23:59) [43]

> Я этой фразы честно сказать не понял, а в справке по bds2006 для Record
> Types написано, что выравнивание в записях производиться по the largest
> alignment of the fields in the record

Выравнивание и размер - разные вещи. Выравнивание говорит о том, откуда пое начинается, размер - где запись заканчивается. Борланд много (но недостаточно - например, не говорит о выравнивании вложенных записей)говорит о выравнивании, но мало о размере записи. В моем примере
t9 = record
i: int64;
b: byte;
end;

понятно, что последний байт данных находится по смещению +8 от начала записи. Логично предположить, что размер записи равен 9. Но это не так по мнению Борланда, он считает, что размер равен 16, т.е. произошло округление вверх до нужной кратности. Замечательно. Пусть будет так.
смотрим на другой пример.
t1 = record
b: byte;
end;

Логично предположить, что в данном случае Борланд поступит аналогично и увеличит размер записи с 1 до 8. Но он этого не делает.
Ага, думаем мы. Наверно это из-за того, что поле одно. Но смотрим дальше.
tt1 = record
b: byte;
b2: byte;
end;

Тут размер равен 2.
А тут 8 и 16:
tt2 = record
b: integer;
b2: byte;
end;


tt2 = record
b: integer;
b2: byte;
end;

Т.е. похоже размер тоже округляется до the largest alignment of the fields in the record

и вроде бы пример
tt1 = record
c: integer;
b2: int64;
c1: integer;
end;


(размер 24) подтверждает это.
Следующий пример(тоже 24) опровергает:
tt1 = record
c: integer;
b2: int64;
c1: byte;
c2: byte;
end;


В общем, ничего сложного :)

> Значит эти модули не попадают под условия перекомпиляции, которые
> описаны в справке, в частности к D7.

Значит условия неверные, если зависимые модули не перекомпилируются.


 
Германн ©   (2008-06-06 00:56) [46]


> > Значит эти модули не попадают под условия перекомпиляции,
>  которые
> > описаны в справке, в частности к D7.
>
> Значит условия неверные, если зависимые модули не перекомпилируются.
>
>

Кстати, лично меня больше беспокоило бы именно это обстоятельство.


 
Sha ©   (2008-06-06 01:05) [47]

> Sha ©   (06.06.08 00:45) [45]
Поправка. Запутался в примерах.
Последний пример ничего не опровергает.

> Т.е. похоже размер тоже округляется до the largest alignment of the fields in the record.
Это, вроде, верно для неупакованных записей.


 
Sha ©   (2008-06-06 01:15) [48]

> Sha ©   (06.06.08 01:05) [47]
Верно, но не всегда
Например,
tt1 = record
b2: int64;
c1: byte;
w: integer;
c2: byte;
end;

имеет размер 20 при {$Align 4} и 24 при {$Align 8}

Т.е. округление производится до largest alignment of the fields in the record,
но не более заданного в {$Align}.
Вроде так.


 
Плохиш ©   (2008-06-06 10:31) [49]


> Sha ©   (06.06.08 00:45) [45]
> > Плохиш ©   (05.06.08 23:59) [43]
>
> > Я этой фразы честно сказать не понял, а в справке по bds2006
> для Record
> > Types написано, что выравнивание в записях производиться
> по the largest
> > alignment of the fields in the record
>
> Выравнивание и размер - разные вещи. Выравнивание говорит
> о том, откуда пое начинается, размер - где запись заканчивается.
>  Борланд много (но недостаточно - например, не говорит о
> выравнивании вложенных записей)говорит о выравнивании, но
> мало о размере записи. В моем примере
> t9 = record
> i: int64;
> b: byte;
> end;
> понятно, что последний байт данных находится по смещению
> +8
от начала записи. Логично предположить, что размер записи
> равен

Т.е. даже справку прочитать не модно, вообще-то там говорится, что для b будет выделено столько же байт, что и для i, храниться b будет в последнем байте этого выделения, а предыдущие байты не используются, т.е. последний байт находится по смещению +15 от начала записи.

PS. Когда-то давно, вроде даже, борланд схематично показывали выравнивание и распределение неупакованных записей.

PPS. Ветка как-то превратилась в переливание из пустого в порожнее :-(


 
Evgeny V ©   (2008-06-06 10:38) [50]


> Sha ©   (05.06.08 17:05) [16]


> Sha ©   (05.06.08 17:12) [19]


Если еще интересны результаты -
t44
D6
В проекте в опциях компилятора стоит Record Field Aligmnet - 8 -> размер структуры всегда 48. Меняем на 4, перекомпилируем -> размер структуры  48, перестраиваем(build) ->размер структуры  44
Видно, что размер структуры выранвнивается на число равное или большее размеру структуры и кратное указанному в параметре Record Field Alignment, и что перекомпиляция не видит изменение этого параметра в проекте...


 
Sha ©   (2008-06-06 10:55) [51]

> Evgeny V ©   (06.06.08 10:38) [50]

Таким образом, компилятор делает примерно следующее.
Для каждого типа данных он знает его максимальные претензии на выравнивание
(например, для целых типов это их размер). Кроме того, у себя в голове он
держит величину выравнивания, заданную в {$Align}, и еще одну переменную,
которая для упакованных записей равна 1, а для неупакованных совпадает {$Align}.
Затем для каждого типа данных компилятор вычисляет минимальные претензии
типа на выравнивание. Это значение равно минимальному из трех, приведенных выше.
В записи поля выравниваются в соответствии с минимальными претензиями на
выравнивание их типов. Размер записи вычисляется как смещение последнего байта
данных плюс 1 и затем округляется в большую сторону до максимального значения
из всех минимальных претензий на выравнивание.
Этот алгоритм применим и к вложенным записям.

Поэтому, например, тип t9
t9 = record
 i: int64;
 b: byte;
 end;

будет иметь длину 9, 10, 12 или 16 в зависимости от значения {$Align},
равного 1, 2, 4 или 8.

К всему этому можно было подойти с другой стороны. Для перемешения к следующему
элементу в массиве записей нам хотелось бы просто увеличивать указатель на размер
записи. Приведенное выше правило в совокупности с правилами выравнивания записей
как раз и обеспечивает такую возможность. На мой взгляд, этим и объясняется
кажущаяся неадекватность компилятора.

Но баг с неперекомпиляцией, конечно, остается багом.


 
Anatoly Podgoretsky ©   (2008-06-06 11:51) [52]

> Sha  (06.06.2008 10:55:51)  [51]

> К всему этому можно было подойти с другой стороны. Для перемешения к следующему
элементу в массиве записей нам хотелось бы просто увеличивать указатель на размер
записи. Приведенное выше правило в совокупности с правилами выравнивания записей
как раз и обеспечивает такую возможность. На мой взгляд, этим и объясняется
кажущаяся неадекватность компилятора.

Это не причем, если перемещение делаешь с помощью SizeOf то без разницы упакованое или нет, истинный размер. А вот то что не перекомпилирует плохо, но это не может привести к ошибке, поскольку если файл с определением изменился, то все зависимые изменятся тоже. Проблема может возникнуть только при передаче данных, но она точно также возникнет и при полной перекомпиляции.
Но можно отметить, что Борланд постоянно играется с выравниванием и его поведением и в тоже время не доводит это дело до конца нет выравнивания на границу 16 байт, а уже актуально и 32 байта.
Документация тоже отстает от реальности.
Пока они не сделали управление выравниванием, у них была одназначность и повторяемость.

> Но баг с неперекомпиляцией, конечно, остается багом.

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

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


 
Sha ©   (2008-06-06 11:54) [53]

> Плохиш ©   (06.06.08 10:31) [49]
> Т.е. даже справку прочитать не модно, вообще-то там говорится, что для
> b будет выделено столько же байт, что и для i, храниться b будет в
> последнем байте этого выделения, а предыдущие байты не используются,
> т.е. последний байт находится по смещению +15 от начала записи.

Неверно.

Попробуй выполнить это, убедишься, что ты не прав.

procedure TForm1.Button1Click(Sender: TObject);
var
 t: t9;
begin
 ShowMessage(IntToStr(pchar(@t.b)-pchar(@t.i)));
end;


> PPS. Ветка как-то превратилась в переливание из пустого в порожнее :-(

У тебя есть право не читать :)


 
Sha ©   (2008-06-06 12:00) [54]

> Anatoly Podgoretsky ©   (06.06.08 11:51) [52]
Зависимые модули не перекомпилируются, если в модуле с определением добавить или удалить packed. Этого для бага достаточно.


 
Плохиш ©   (2008-06-06 13:42) [55]


> Sha ©   (06.06.08 11:54) [53]
> > Плохиш ©   (06.06.08 10:31) [49]
> > Т.е. даже справку прочитать не модно, вообще-то там говорится,
>  что для
> > b будет выделено столько же байт, что и для i, храниться
> b будет в
> > последнем байте этого выделения, а предыдущие байты не
> используются,
> > т.е. последний байт находится по смещению +15 от начала
> записи.
>
> Неверно.

Действительно неправ, как-то вылетело, что младший байт храниться по младшему адресу. Но предположение о размере записи всё-равно нелогично, так как для последнего поля выделяется один байт, только в одном случае, когда выравнивание установлено в 1 {A1}.

> Sha ©   (06.06.08 12:00) [54]
> Зависимые модули не перекомпилируются, если в модуле с определением
> добавить или удалить packed. Этого для бага достаточно.

Судя по справке к D7, это не баг, а фича, т.к. описано. А вот для BDS2006 это бага, там в справке Compiling Applications третим пунктом стоит, что при запуске на выполнение, перекомпилируются также и все зависимые модули.


 
Anatoly Podgoretsky ©   (2008-06-06 13:56) [56]

> Sha  (06.06.2008 12:00:54)  [54]

Тогда согласен, но это странно, ведь перекомпиляция основана на факте изменения даты, а не содержимого.
Если это так, то это определенно баг, но он должен касаться любых изменений.
А вот настройки в среде другое дело, но я привык делать Build при изменение настроек.


 
Sha ©   (2008-06-06 14:03) [57]

> Плохиш ©   (06.06.08 13:42) [55]
> для последнего поля выделяется один байт, только в одном случае, когда выравнивание установлено в 1 {A1}.

Здесь, конечно, дело вкуса.

Тебе почему-то удобней думать, что последнее поле, в котором лежит однобайтовая переменная, занимает 8 байт, несмотря на то, что компилятор с ним оперирует именно как с одним байтом во всех операциях (арифметика, логика, пересылка). Твое право.

Я определяю размер поля по тому, как с ним работает компилятор. Так моим мозгам удобнее.


 
Sha ©   (2008-06-06 14:05) [58]

> Anatoly Podgoretsky ©   (06.06.08 13:56) [56]
> но он должен касаться любых изменений...

Любых не касается.
Например, если изменить тип поля, все компилирутся как надо.


 
Anatoly Podgoretsky ©   (2008-06-06 14:41) [59]

> Sha  (06.06.2008 14:05:58)  [58]

Добавление Packed это по сути и есть изменение типа поля.
Но я уже писал, что перекомпиляция связаных модулей не зависит от содержимого, а только от дат, основано на make.
А по твоим словам ты же именно модуль меняешь


 
Sha ©   (2008-06-06 14:52) [60]

> Anatoly Podgoretsky ©   (06.06.08 14:41) [59]

Это не я писал, хотя это верно :)
Последовательность действий по воспроизведению бага описана [16].
Тут суть в том, что модули на диске не перезаписываются и дата у них не меняется.
Изменения делаются непосредственно в среде Дельфи.
И некоторые из них Дельфи учитывает в зависимых модулях, а некоторые - нет.


 
Anatoly Podgoretsky ©   (2008-06-06 15:09) [61]

> Sha  (06.06.2008 14:52:00)  [60]

Я уже матюгался? Нет, ну тогда матюгаюсь, Борланд пошел по попсовому пути, набросать много не нужных функций, и попутно теряя надежность компилятора, делая всякие колокольчики. А переход к ebarcader может ситуацию еще больше ухудшить. Все лучшие кадры подарили или Микрософту или Ораклу и другим фирмам.


 
Плохиш ©   (2008-06-06 15:15) [62]


> Sha ©   (06.06.08 14:03) [57]
> > Плохиш ©   (06.06.08 13:42) [55]
> > для последнего поля выделяется один байт, только в одном
> случае, когда выравнивание установлено в 1 {A1}.
>
> Здесь, конечно, дело вкуса.
>
> Тебе почему-то удобней думать, что последнее поле, в котором
> лежит однобайтовая переменная, занимает 8 байт,

Согласись, что понятия "занимает байт" и "распределено байт" несколько отличаются. И мне как-то удобней думать, что структуры данных занимают столько байт, как это описано в документации разработчиков компилятора.


 
Плохиш ©   (2008-06-06 15:16) [63]


> Anatoly Podgoretsky ©   (06.06.08 15:09) [61]

+1 :-(


 
имя   (2008-06-06 15:23) [64]

Удалено модератором
Примечание: offtopic


 
Sha ©   (2008-06-06 15:30) [65]

Удалено модератором
Примечание: offtopic


 
Anatoly Podgoretsky ©   (2008-06-06 15:34) [66]

Удалено модератором
Примечание: offtopic


 
имя   (2008-06-06 15:40) [67]

Удалено модератором
Примечание: offtopic


 
Плохиш ©   (2008-06-06 15:46) [68]

Нифигасе, страсти накалились 8-O


 
Sha ©   (2008-06-06 16:40) [69]

> Плохиш ©   (06.06.08 15:15) [62]

Вот пример, который прояснит мою позицию.
Известно, что память в Д7 под строки выделяется двойными словами. И если длина строки кратна 4, то терминатор попадает в отдельный dword. Но никому ведь не приходит в голову говорить, что терминатор занимает или под него выделено двойное слово, потому что три лишних байта потребовались строке в целом, а не терминатору. Т.е. размер строки был округлен до 4 вверх.
Так и случае с записями. Лишние байты не принадлежат последнему полю. На мой взгляд.


 
Anatoly Podgoretsky ©   (2008-06-06 16:45) [70]

Это понятно, но это психология, тут претензии только к Борланду, а есть ли при работе ошибка?


 
Palladin ©   (2008-06-06 16:57) [71]


> Лишние байты не принадлежат последнему полю.

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

интересный эксперимент
{$A8}
TMR1=Record
 a:Byte;
 // - щель 1b
 c:Word;
 d:Byte;
 // - щель 1b
 e:Word;
End; // 8b

TMR2=Record
 a:Byte;
 // 1b
 c:Word;
 // 2b
 d:Byte;
 // 3b
 e:Integer;
End; // 12b

хотя

{$A2}
TMR1=Record
 a:Byte;
 // - щель 1b
 c:Word;
 d:Byte;
 // - щель 1b
 e:Word;
End; // 8b

TMR2=Record
 a:Byte;
 // 1b
 c:Word;
 // 2b
 d:Byte;
 // 1b
 e:Integer;
End; // 10b


 
Palladin ©   (2008-06-06 17:07) [72]

в последнем типе ошибся

{$A2}
TMR2=Record
a:Byte;
// 1b
c:Word;
d:Byte;
// 1b
e:Integer;
End; // 10b


 
Palladin ©   (2008-06-06 17:58) [73]

так, еще раз и без косяков... :)

{$A8}
TMR1=Record
 a:Byte;
 "просвет" 1b
 c:Word;
 d:Byte;
 "просвет" 1b
 e:Word;
End; 8b

TMR2=Record
 a:Byte;
 "просвет" 1b
 c:Word;
 d:Byte;
 "просвет" 3b
 e:Integer;
End; 12b

{$A2}
TMR1=Record
 a:Byte;
 "просвет" 1b
 c:Word;
 d:Byte;
 "просвет" 1b
 e:Word;
End; 8b

TMR2=Record
 a:Byte;
 "просвет" 1b
 c:Word;
 d:Byte;
 "просвет" 1b
 e:Integer;
End; 10b


 
Sha ©   (2008-06-06 18:32) [74]

> Anatoly Podgoretsky ©   (06.06.08 16:45) [70]
> ... а есть ли при работе ошибка?

В [51] я попытался кратко изложить логику работы компилятора при выравнивании полей записи и определении размера записи.
Более того, Борланд следует приведенному алгоритму и во вложенных структурах.
Ошибок не обнаружено :)

Там же я сделал предположение, зачем потребовался такой не совсем очевидный алгоритм определения размера записи.
Здесь у Борланда все сходится идеально.


 
tesseract ©   (2008-06-06 19:37) [75]


> зачем потребовался такой не совсем очевидный алгоритм определения
> размера записи.


Может связано с оптимизацией работы кучи ?


 
Anatoly Podgoretsky ©   (2008-06-07 01:18) [76]

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


 
KSergey ©   (2008-06-07 09:42) [77]

Может и не в тему
http://forum.sources.ru/index.php?showtopic=110906

Формально по ссылке наверное написано правильно, но, если честно, моему осознанию сильно мешает то, что автор не привел свое толкование примененных теринов.
На сколько я смог понять, между словами "выравнивание" и "размер" у него подразумевается знак равенства.


 
KSergey ©   (2008-06-07 11:45) [78]

> KSergey ©   (07.06.08 09:42) [77]
> Формально по ссылке наверное написано правильно,

Беда только в том, что не про дельфи :)
Но это обсуждение натолкнуло меня на мысль, что в дельфи у автора оно как-то примерно так же устроено, похоже.



Страницы: 1 2 вся ветка

Текущий архив: 2009.08.30;
Скачать: CL | DM;

Наверх




Память: 0.66 MB
Время: 0.019 c
4-1216031319
Dash Rendar
2008-07-14 14:28
2009.08.30
Как запустить свое приложение вместо проводника?


15-1246448096
palva
2009-07-01 15:34
2009.08.30
Умерла Людмила Зыкина


1-1213454201
cavalera
2008-06-14 18:36
2009.08.30
Почему не хочет загружаться процедура из dll.


2-1246216548
Pasha
2009-06-28 23:15
2009.08.30
Обращение к ячейкам в БД


2-1246604370
Neket
2009-07-03 10:59
2009.08.30
Как узнать колличество записей в DBGrid?