Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2009.08.30;
Скачать: [xml.tar.bz2];

Вниз

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

 
Sha ©   (2008-06-05 16:25) [0]

Моя 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;


 
Palladin ©   (2008-06-05 16:28) [1]

с месяца два я распинался уже в "прочее" про выравниванивание полей в структурах... поди уже в архиве...


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

оно вполне адекватное... приводи, обосную :)


 
Sha ©   (2008-06-05 16:30) [2]

> Palladin ©   (05.06.08 16:28) [1]

я не спрашивал про выравнивание


 
Palladin ©   (2008-06-05 16:31) [3]


> Sha ©   (05.06.08 16:30) [2]

а размер записи напрямую зависит от выравнивания


 
Palladin ©   (2008-06-05 16:37) [4]

а так же от расположения полей

Type
TRec1=Record
 a:Int64;
 b:Byte;
 c:Integer;
 d:Byte;
End;

TRec2=Record
 a:Int64;
 b:Byte;
 d:Byte;
 c:Integer;
End;


абсолютно разные SizeOf, если немного поэкспериментировать, можно выявить как компилятор упаковывает поля записи и как влияет на упаковку директива {$A}


 
Sha ©   (2008-06-05 16:39) [5]

> Palladin ©   (05.06.08 16:31) [3]

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

Move(r1,abc,SizeOf(t1)); //тут скопируется 1 байт
Move(r5,abc,SizeOf(t5)); //тут скопируется 8 байт, а не 5, как ожидаю я


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


> Sha ©   (05.06.08 16:25)  
> Моя Delphi7 выводит 1 2 4 8 16 16 16 16 в качестве размеров
> структур, имеющих размер 1, 2, 4, 8, 9, 10, 12, 16 байт.

Пиши packed record и получишь желаемые цифры.


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


> Про выравнивание все ясно, и что размер записи зависит от
> выранивания тоже ясно.
> Только неясно, почему t1 имеет размер 1 байт, а t5 - 8.

Хм, решил мне телепатор сломать, не выйдет...


 
Palladin ©   (2008-06-05 16:46) [8]

1. по видимому, компилятор воспринимает запись из одного поля, как просто тип этого поля
2. move вообще опасно применять к не packed записям, программист всегда должен иметь ввиду, что размер записи может не совпадать, не то чтобы с  суммой размеров полей, но и быть разным даже в зависимости от директив и настроек компилятора.


 
Anatoly Podgoretsky ©   (2008-06-05 16:48) [9]

> Sha  (05.06.2008 16:25:00)  [0]

В чем неадекватность, и наверно твое представление не совпадает с представлением компилятора, а понять его не всегда легко.


 
Sha ©   (2008-06-05 16:49) [10]

> Плохиш ©   (05.06.08 16:43) [7]

С чего все началось. Было замечено , что тип t44 независио от packed, но в зависимости от расположения звезд на небе имеет размер 44 или 48 байт

 t44 = record
 i1: int64;
 i2: int64;
 i3: int64;
 i4: int64;
 d1: dword;
 d2: dword;
 d3: dword;
 end;


 
Anatoly Podgoretsky ©   (2008-06-05 16:49) [11]

> Sha  (05.06.2008 16:25:00)  [0]

Кстати если тебе нужна адекватность, то используй слово Packed


 
Sha ©   (2008-06-05 16:51) [12]

> Palladin ©   (05.06.08 16:46) [8]
> move вообще опасно применять к не packed записям

и как показывает пост [10] и к Packed тоже


 
Sha ©   (2008-06-05 16:52) [13]

> Anatoly Podgoretsky ©   (05.06.08 16:49) [11]

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

Вопрос в том, есть этот глюк в новых версиях Дельфи


 
Palladin ©   (2008-06-05 16:53) [14]


> Sha ©   (05.06.08 16:49) [10]

ну, я думаю это что то не реальное. у меня стабильно у packed 44. как воспроизвести?


 
Anatoly Podgoretsky ©   (2008-06-05 16:55) [15]

> Sha  (05.06.2008 16:30:02)  [2]

А как ты это представляешь, выравнивание без изменения размера?


 
Sha ©   (2008-06-05 17:05) [16]

> Palladin ©   (05.06.08 16:53) [14]
> ну, я думаю это что то не реальное. у меня стабильно у packed 44. как воспроизвести?

Ты под другими звездами :)

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

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


 
Sha ©   (2008-06-05 17:06) [17]

> Anatoly Podgoretsky ©   (05.06.08 16:55) [15]
> А как ты это представляешь, выравнивание без изменения размера?

Не понял


 
Anatoly Podgoretsky ©   (2008-06-05 17:07) [18]

> Sha  (05.06.2008 16:52:13)  [13]

Не знаю, никогда не заморачивался этой проблемой.
Но Packed всегда работал ожидаемо.


 
Sha ©   (2008-06-05 17:12) [19]

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

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

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


 
Sha ©   (2008-06-05 17:13) [20]

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

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

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

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


 
oxffff ©   (2008-06-05 17:15) [21]


> Sha ©   (05.06.08 16:25)  


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


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

Исправления в пост [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, как ожидаю я


 
Kolan ©   (2008-06-05 17:17) [23]


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

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


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

1 2 4 8 16 16 16 16

Turbo Delphi 2006


 
Kolan ©   (2008-06-05 17:20) [25]

RAD 2007
1 2 4 8 16 16 16 16

BDS 2006
1 2 4 8 16 16 16 16


 
Sha ©   (2008-06-05 17:20) [26]

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

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

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


 
Sha ©   (2008-06-05 17:22) [27]

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

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


 
Sha ©   (2008-06-05 17:23) [28]

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

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


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


> 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.


 
Palladin ©   (2008-06-05 18:16) [30]


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

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


 
Sha ©   (2008-06-05 20:04) [31]

> Плохиш ©   (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.


 
Sha ©   (2008-06-05 21:09) [32]

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

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

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


 
Anatoly Podgoretsky ©   (2008-06-05 21:19) [33]

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

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

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


 
Anatoly Podgoretsky ©   (2008-06-05 21:49) [34]

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

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


 
Sha ©   (2008-06-05 22:16) [35]

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

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


 
Anatoly Podgoretsky ©   (2008-06-05 22:29) [36]

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

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


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

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


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

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


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


> Sha ©   (05.06.08 20:04) [31]
> > Плохиш ©   (05.06.08 18:01) [29]


> > If two fields share a common type specification,
>
> А это ты к чему? У меня такого нет.

Вообщв-то, в следующих букавках приводиться пример, почему запись T9 имеет размер 16 байт, а неожидаемый, почему-то, тобой 9 байт. Конечно, борланд поступил нехорошо не указав в примере все возможные комбинации записей.

PS. Хотите верить в чудеса, так пожалуйста, никто не запрещает...


 
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-его)

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



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

Форум: "Основная";
Текущий архив: 2009.08.30;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.58 MB
Время: 0.009 c
15-1245954371
Kerk
2009-06-25 22:26
2009.08.30
ICFP


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


2-1246461858
Zheksonz
2009-07-01 19:24
2009.08.30
strn:=#01#06#00#04#19#136;


3-1226317055
ssa
2008-11-10 14:37
2009.08.30
перенос текстовых данных с Дельфи формы в таблицу Oracle


15-1246307568
Юрий
2009-06-30 00:32
2009.08.30
С днем рождения ! 30 июня 2009 вторник





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский