Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Насколько адекватен SizeOf


Страницы:   1 2 3 4

Sha ©   (2008-06-05 16:25:00) 

Моя Delphi7 выводит 1 2 4 8 16 16 16 16 в качестве размеров структур, имеющих размер 1, 2, 4, 8, 9, 10, 12, 16 байт.
Также замечено неадекватное поведение и для структур большего размера.

Интересны результаты для других версий Delphi.

Тестилось на этом коде

type

 t1 = record
 b: byte;
 end;

 t2 = record
 w: word;
 end;

 t4 = record
 d: dword;
 end;

 t8 = record
 i: int64;
 end;

 t9 = record
 i: int64;
 b: byte;
 end;

 t10 = record
 i: int64;
 w: word;
 end;

 t12 = record
 i: int64;
 d: dword;
 end;

 t16 = record
 i: int64;
 i2: int64;
 end;

procedure TForm1.FormCreate(Sender: TObject);
begin
 Edit1.Text:=Format('%d %d %d %d %d %d %d %d',
 [SizeOf(t1), SizeOf(t2), SizeOf(t4), SizeOf(t8),
  SizeOf(t9), SizeOf(t10), SizeOf(t12), SizeOf(t16)]);
end;


просто так   (2008-06-05 22:43:00) [41]

про compile и build - проскакивают старые dcu, d7 и d2006 с этим ведут себя одинакого помоему


просто так   (2008-06-05 22:39:00) [42]

в d7 разбирался с выравниванием, сложного ниче небыло, работали сложные структуры без packed. позже пришлось вообще отказаться от выравнивания изза переезда на fpc


Anatoly Podgoretsky   (2008-06-05 22:29:00) [43]

> Sha  (05.06.2008 22:16:35)  [35]

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


Sha   (2008-06-05 22:16:00) [44]

> Anatoly Podgoretsky ©   (05.06.08 21:49) [34]

Да не, нормально, если все делать, как в [31].
Вот только контролировать - проблема, есть шанс не заметить не пакед структуру.


Anatoly Podgoretsky   (2008-06-05 21:49:00) [45]

> Sha  (05.06.2008 21:09:32)  [32]

Ой это вообще делает ситуацию неопределенной.


Anatoly Podgoretsky   (2008-06-05 21:19:00) [46]

> Sha  (05.06.2008 20:04:31)  [31]

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

Раз знаешь как обойти, то плюнь и отойди.


Sha   (2008-06-05 21:09:00) [47]

В проекте используются вложенные структуры данных.
Я написал небольшой тест для них:

type
 T1n= record
   a: byte;
   end;
 T1p= packed record
   a: byte;
   end;
 T2n= record
   a: integer;
   b: byte;
   end;
 T2p= packed record
   a: integer;
   b: byte;
   end;

 T11nn= packed record
   a: T1n;
   b: T1n;
   end;
 T11np= packed record
   a: T1n;
   b: T1p;
   end;
 T11pn= packed record
   a: T1p;
   b: T1n;
   end;
 T11pp= packed record
   a: T1p;
   b: T1p;
   end;

 T21nn= packed record
   a: T2n;
   b: T1n;
   end;
 T21np= packed record
   a: T2n;
   b: T1p;
   end;
 T21pn= packed record
   a: T2p;
   b: T1n;
   end;
 T21pp= packed record
   a: T2p;
   b: T1p;
   end;

 T22nn= packed record
   a: T2n;
   b: T2n;
   end;
 T22np= packed record
   a: T2n;
   b: T2p;
   end;
 T22pn= packed record
   a: T2p;
   b: T2n;
   end;
 T22pp= packed record
   a: T2p;
   b: T2p;
   end;

 N11nn= record
   a: T1n;
   b: T1n;
   end;
 N11np= record
   a: T1n;
   b: T1p;
   end;
 N11pn= record
   a: T1p;
   b: T1n;
   end;
 N11pp= record
   a: T1p;
   b: T1p;
   end;

 N21nn= record
   a: T2n;
   b: T1n;
   end;
 N21np= record
   a: T2n;
   b: T1p;
   end;
 N21pn= record
   a: T2p;
   b: T1n;
   end;
 N21pp= record
   a: T2p;
   b: T1p;
   end;

 N22nn= record
   a: T2n;
   b: T2n;
   end;
 N22np= record
   a: T2n;
   b: T2p;
   end;
 N22pn= record
   a: T2p;
   b: T2n;
   end;
 N22pp= record
   a: T2p;
   b: T2p;
   end;

procedure TForm1.Button1Click(Sender: TObject);
begin
Memo1.Lines.Add(Format('T1n=%d T1p=%d',
[SizeOf(T1n), SizeOf(T1p)]));

Memo1.Lines.Add(Format('T2n=%d T2p=%d',
[SizeOf(T2n), SizeOf(T2p)]));

Memo1.Lines.Add(Format('T11nn=%d T11np=%d T11pn=%d T11pp=%d',
[SizeOf(T11nn), SizeOf(T11np), SizeOf(T11pn), SizeOf(T11pp)]));

Memo1.Lines.Add(Format('T21nn=%d T21np=%d T21pn=%d T21pp=%d',
[SizeOf(T21nn), SizeOf(T21np), SizeOf(T21pn), SizeOf(T21pp)]));

Memo1.Lines.Add(Format('T22nn=%d T22np=%d T22pn=%d T22pp=%d',
[SizeOf(T22nn), SizeOf(T22np), SizeOf(T22pn), SizeOf(T22pp)]));

Memo1.Lines.Add(Format('N11nn=%d N11np=%d N11pn=%d N11pp=%d',
[SizeOf(N11nn), SizeOf(N11np), SizeOf(N11pn), SizeOf(N11pp)]));

Memo1.Lines.Add(Format('N21nn=%d N21np=%d N21pn=%d N21pp=%d',
[SizeOf(N21nn), SizeOf(N21np), SizeOf(N21pn), SizeOf(N21pp)]));

Memo1.Lines.Add(Format('N22nn=%d N22np=%d N22pn=%d N22pp=%d',
[SizeOf(N22nn), SizeOf(N22np), SizeOf(N22pn), SizeOf(N22pp)]));
end;

Получен результат:

T1n=1 T1p=1
T2n=8 T2p=5
T11nn=2 T11np=2 T11pn=2 T11pp=2
T21nn=9 T21np=9 T21pn=6 T21pp=6
T22nn=16 T22np=13 T22pn=13 T22pp=10
N11nn=2 N11np=2 N11pn=2 N11pp=2
N21nn=12 N21np=12 N21pn=6 N21pp=6
N22nn=16 N22np=16 N22pn=16 N22pp=10

Мне не удалось двумя словами описать правила, которыми руководствуется компилятор.
Может, кто-нибудь сможет? :)


Sha   (2008-06-05 20:04:00) [48]

> Плохиш ©   (05.06.08 18:01) [29]
> 2. Компиляция затрагивает только те модули, исходник которых был изменён

Это неверно.
Пример.

Добавляем в проект модуль

unit SizeOfU2;

interface

type
 TMy1= integer;
 TMy2= record
   pref: int64;
   i2: integer;
   end;

implementation

end.


и кнопку

uses
 SizeOfU2;

procedure TForm1.Button1Click(Sender: TObject);
var
 i1: TMy1;
 i2: TMy2;
begin
Edit1.Text:=Format('%d %d',
[SizeOf(TMy1), SizeOf(TMy2)]);
end;



компилируем, пускаем, жмем, получаем размеры 4,16
вносим изменения только в добавленный модуль   TMy1= int64;
компилируем, пускаем, жмем, получаем размеры 8,16
вносим изменения только в добавленный модуль   TMy2= packed record
компилируем, пускаем, жмем, получаем размеры 8,16
билдим, пускаем, жмем, получаем размеры 8,12

Ситуация усугубляется, если имеется группа проектов.

> Хм, а почему ты ожидаешь не то, что описано в справке?

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

> If two fields share a common type specification,

А это ты к чему? У меня такого нет.

P.S.
Ну и еще раз. У меня нет проблем. Я знаю как все это обойти. Мне просто хотелось более адекватного поведения компилятора. Надеялся, что в новых версиях эти грабли отсутствуют. Видно, придется и дальше использовать packed, а чтоб он не ломал выравнивание вводить резервные поля, после каждого изменения packed/не packed перебилдивать, и чтоб уж совсем параноидально застраховаться от ошибочного убирания packed в будущем дополнять запись какой-нить фигней до размера, кратного 16.


Palladin   (2008-06-05 18:16:00) [49]


> проверяется, кстати, по дате.

этот нюанс, кстати, тоже все время ввиду иметь нужно... решение, мягко говоря, ненадежное и приводит иногда к эффекту, тех самых, космических лучей :)...


Плохиш   (2008-06-05 18:01:00) [50]


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


> Последовательность дейсвий такая.
> Убираем packed, билдим проект, получаем 48
> Ставим packed, компилируем, получаем 48
> Билдим, получаем 44


Ну и? Всё описано в документации.
1. SizeOf для типа - константа, которая будет вставлена при компиляции в dcu.
2. Компиляция затрагивает только те модули, исходник которых был изменён, проверяется, кстати, по дате. Соответственно при сборке будут взяты dcu со старым значением SizeOf.
3. Build перекомпилирует все модули, соответственно получаем новые значения размеров.

> Sha ©   (05.06.08 17:17) [22]
> Move(r1,abc,SizeOf(t1)); //тут скопируется 1 байт
> Move(r9,abc,SizeOf(t9)); //тут скопируется 16 байт, а не
> 9, как ожидаю я

Хм, а почему ты ожидаешь не то, что описано в справке?

If two fields share a common type specification, they are packed even if the declaration does not include the packed modifier and the record type is not declared in the {$A-} state. Thus, for example, given the following declaration
type
 TMyRecord = record
   A, B: Extended;  
   C: Extended;
 end;
A and B are packed (aligned on byte boundaries) because they share the same type specification. The compiler pads the structure with unused bytes to ensure that C appears on a quadword boundary.


Sha   (2008-06-05 17:23:00) [51]

> Sha ©   (05.06.08 17:20) [26]
> oxffff ©   (05.06.08 17:15) [21]

Причем может скопироваться и 44,в зависимости от истории исправлений см [16]


Sha   (2008-06-05 17:22:00) [52]

> Игорь Шевченко ©   (05.06.08 17:18) [24]
> Kolan ©   (05.06.08 17:20) [25]

Понятно, спасибо, будем иметь ввиду


Sha   (2008-06-05 17:20:00) [53]

> oxffff ©   (05.06.08 17:15) [21]
Меня не устраивает, что я должен искать обходные пути для копирования типа t44, даже если он packed

Move(r44,abc,SizeOf(t44)); //тут скопируется 48 байт, а не 44, как ожидаю я

Но не этом вопрос, а про другие весии Дельфи


Kolan   (2008-06-05 17:20:00) [54]

RAD 2007
1 2 4 8 16 16 16 16

BDS 2006
1 2 4 8 16 16 16 16


Игорь Шевченко   (2008-06-05 17:18:00) [55]

1 2 4 8 16 16 16 16

Turbo Delphi 2006


Kolan   (2008-06-05 17:17:00) [56]


> Интересны результаты для других версий Delphi.

Для каких других?


Sha   (2008-06-05 17:17:00) [57]

Исправления в пост [5]

для
> Palladin ©   (05.06.08 16:31) [3]
>Плохиш ©   (05.06.08 16:43) [7]

Про выравнивание все ясно, и что размер записи зависит от выранивания тоже ясно.
Только неясно, почему t1 имеет размер 1 байт, а t9- 16.
Это может примести к ошибкам в операторах типа

Move(r1,abc,SizeOf(t1)); //тут скопируется 1 байт
Move(r9,abc,SizeOf(t9)); //тут скопируется 16 байт, а не 9, как ожидаю я


oxffff   (2008-06-05 17:15:00) [58]


> Sha ©   (05.06.08 16:25)  


Можете как то доступно объянить в что вас конкретно не устраивает. Логика выравнивания?
Вы хотите сказать что компилятор самопроизвольно меняет размер записи и факт того , что две идентичных записи не смогут корректно взаимодейстовать скомпилированных раздельно если звезда моргнет?


Sha   (2008-06-05 17:13:00) [59]

Сорь, не так цитатки поставил

> Anatoly Podgoretsky ©   (05.06.08 17:07) [18]
Мы тоже всегда используем packed. Он работает ожидаемо. Неожиданно работает SizeOf :)

Еще раз повторюсь, не надо советов, что мне надо сделать.

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


Sha   (2008-06-05 17:12:00) [60]

> Anatoly Podgoretsky ©   (05.06.08 17:07) [18]
> Мы тоже всегда используем packed. Он работает ожидаемо. Неожиданно работает SizeOf :)

Еще раз повторюсь, не надо советов, что мне надо сделать.

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


Страницы:   1 2 3 4

Наверх

Титульная страница Поиск, карта сайта Написать письмо