Конференция "Основная" » Насколько адекватен SizeOf
 
  • Sha © (05.06.08 17:13) [20]
    Сорь, не так цитатки поставил

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

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

    Просьба, скомпилировать исходный пример и запустить под другими версиями Дельфи.
  • oxffff © (05.06.08 17:15) [21]

    > Sha ©   (05.06.08 16:25)  


    Можете как то доступно объянить в что вас конкретно не устраивает. Логика выравнивания?
    Вы хотите сказать что компилятор самопроизвольно меняет размер записи и факт того , что две идентичных записи не смогут корректно взаимодейстовать скомпилированных раздельно если звезда моргнет?
  • Sha © (05.06.08 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 © (05.06.08 17:17) [23]

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

    Для каких других?
  • Игорь Шевченко © (05.06.08 17:18) [24]
    1 2 4 8 16 16 16 16

    Turbo Delphi 2006
  • Kolan © (05.06.08 17:20) [25]
    RAD 2007
    1 2 4 8 16 16 16 16

    BDS 2006
    1 2 4 8 16 16 16 16
  • Sha © (05.06.08 17:20) [26]
    > oxffff ©   (05.06.08 17:15) [21]
    Меня не устраивает, что я должен искать обходные пути для копирования типа t44, даже если он packed

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

    Но не этом вопрос, а про другие весии Дельфи
  • Sha © (05.06.08 17:22) [27]
    > Игорь Шевченко ©   (05.06.08 17:18) [24]
    > Kolan ©   (05.06.08 17:20) [25]

    Понятно, спасибо, будем иметь ввиду
  • Sha © (05.06.08 17:23) [28]
    > Sha ©   (05.06.08 17:20) [26]
    > oxffff ©   (05.06.08 17:15) [21]

    Причем может скопироваться и 44,в зависимости от истории исправлений см [16]
  • Плохиш © (05.06.08 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 © (05.06.08 18:16) [30]

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

    этот нюанс, кстати, тоже все время ввиду иметь нужно... решение, мягко говоря, ненадежное и приводит иногда к эффекту, тех самых, космических лучей :)...
  • Sha © (05.06.08 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 © (05.06.08 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 © (05.06.08 21:19) [33]
    > Sha  (05.06.2008 20:04:31)  [31]

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

    Раз знаешь как обойти, то плюнь и отойди.
  • Anatoly Podgoretsky © (05.06.08 21:49) [34]
    > Sha  (05.06.2008 21:09:32)  [32]

    Ой это вообще делает ситуацию неопределенной.
  • Sha © (05.06.08 22:16) [35]
    > Anatoly Podgoretsky ©   (05.06.08 21:49) [34]

    Да не, нормально, если все делать, как в [31].
    Вот только контролировать - проблема, есть шанс не заметить не пакед структуру.
  • Anatoly Podgoretsky © (05.06.08 22:29) [36]
    > Sha  (05.06.2008 22:16:35)  [35]

    Согласен, но у меня проблем не возникало, может потому что я недопускаю неодназначных конструкций и не использую конструкции типа низкоуровневого Move и подобных. Вот когда коснется, вот тогда и буду разбираться.
  • просто так (05.06.08 22:39) [37]
    в d7 разбирался с выравниванием, сложного ниче небыло, работали сложные структуры без packed. позже пришлось вообще отказаться от выравнивания изза переезда на fpc
  • просто так (05.06.08 22:43) [38]
    про compile и build - проскакивают старые dcu, d7 и d2006 с этим ведут себя одинакого помоему
  • Плохиш © (05.06.08 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. Хотите верить в чудеса, так пожалуйста, никто не запрещает...
 
Конференция "Основная" » Насколько адекватен SizeOf
Есть новые Нет новых   [134491   +8][b:0][p:0.003]