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

Вниз

Delphi 2009 - запись с вариантной частью   Найти похожие ветки 

 
Чайник ©   (2009-06-30 21:02) [0]

Перенос проекта из D7 в D2009:

Объявление типа:

  TtcMixture = record //Состав газовой смеси
     Name : string[64];
     MixtureKind : TtcMixtureKind;
     Ro, Mu, Cp, Cv, Hs : Extended;
     case Vid : Boolean of
     False : (N2, Ar, O2, H2O, CO, CO2, CH4 : Extended);
     True  : (Comp : array[1..7] of Extended);
  end;


В D7 все работало нормально, т.е. операторы вида

Mix.N2 := 0.7809 и Mix.Сomp[0] := 0.7809 эавивалентны.

В D2009 - такое впечатление, что вариантные части в разных областях памяти - Mix.N2 и Mix.Сomp[0] не зависимы друг от друга.
Что делать?


 
Чайник ©   (2009-06-30 21:15) [1]

Заменил record на packed record - заработало.
И что бы это значило?


 
Юрий Зотов ©   (2009-07-01 00:44) [2]

> И что бы это значило?

Поля N2, Ar, O2, H2O, CO, CO2, CH4 выравниваются, а массив packed, его элементы не выравниваются.


 
Германн ©   (2009-07-01 01:03) [3]


> Юрий Зотов ©   (01.07.09 00:44) [2]
>
> > И что бы это значило?
>
> Поля N2, Ar, O2, H2O, CO, CO2, CH4 выравниваются, а массив
> packed, его элементы не выравниваются.
>

Точнее это значит, что в Дельфи есть опция компилятора  $A. И она может настраиваться.
А packed следует применять сейчас только в особых случаях. Например, когда данная запись должна иметь возможность рассматриваться "с точностью" до байта.

P.S.
И не массив packed, Юр. А запись packed.


 
Юрий Зотов ©   (2009-07-01 01:20) [4]

> Германн ©   (01.07.09 01:03) [3]

> И не массив packed, Юр. А запись packed.

Лучше не спорь. И людей не путай.


 
Германн ©   (2009-07-01 01:39) [5]


> Юрий Зотов ©   (01.07.09 01:20) [4]
>
> > Германн ©   (01.07.09 01:03) [3]
>
> > И не массив packed, Юр. А запись packed.
>
> Лучше не спорь. И людей не путай.
>

Спорить с тобой? Я не на столько дурак. :)
Но людей я вроде как не путаю.
Речь в сабже шла о packed record, а не о packed array.
Хотя, иногда, можно и с ЮЗ поспорить. :)


 
Юрий Зотов ©   (2009-07-01 08:24) [6]

> Германн ©   (01.07.09 01:39) [5]

Спорить можно с кем угодно, если по делу. Но не в данном случае, потому что ты просто не понял.

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

type
 TRec = record
   case boolean of
     False : (F1, F2: extended);
     True  : (A : array[1..2] of extended);
 end;
 
 TPackRec = packed record
   case boolean of
     False : (F1, F2: extended);
     True  : (A : array[1..2] of extended);
 end;

var
 R: TRec;
 PR: TPackRec;

=================

for i := 1 to 2 do // Заполняем обе записи
begin
 R.A[i] := i;
 PR.A[i] := i
end;

Учитывая, что SizeOf(extended)=10, теперь получим, что R.F1<>R.A[1] и R.F2<>R.A[2], хотя PR.F1=PR.A[1] и PR.F2=PR.A[2]. Дело в том, что массив всегда packed, даже и без явного объявления (как ни странно, но почему-то это так). И выходит, что в записи R поля F1 и F2 не совпадают с элементами массива A (поскольку поля F1 и F2 невыравнены, а массив выравнен), а в записи PR - совпадают (поскольку и эти поля, и массив выравнены).

Вообще говоря, это различие между R и PR должно проявляться во всех версиях Delphi. Почему у автора оно не провляется в D7 и проявляется в D2009 - непонятно. Можно предположить 2 причины:

1. В настройках компилятора D7 у него проставлено дефолтное выравнивание полей записей на границу байта (что эквивалентно packed), а в D2009 - другое.

2. Каждый компилятор что-то с  выравниванием химичит, причем каждый по-своему. Как ни фантастично это предположение выглядит (и похоже на баг), оно, тем не менее, правдоподобно - потому что в D7 разница между R и PR действительно не проявляется при любом дефолтном выравнивании. Только что проверил это на практике (при дефолтном выравнивании на границу двойного слова):

procedure TForm1.FormCreate(Sender: TObject);
var
 i: integer;
begin
 for i := 1 to 2 do
 begin
   R.A[i] := i;
   PR.A[i] := i;
   ListBox1.Items.Add(FloatToStr(R.A[i])); // 1 и 2, как и должно быть
   ListBox2.Items.Add(FloatToStr(PR.A[i])) // 1 и 2, как и должно быть
 end;
 ListBox1.Items.Add(FloatToStr(R.F1)); // 1, как НЕ должно быть
 ListBox1.Items.Add(FloatToStr(R.F2)); // 2, как НЕ должно быть
 ListBox1.Items.Add(IntToStr(SizeOf(R))); // 24, как и должно быть
 ListBox2.Items.Add(FloatToStr(PR.F1)); // 1, как и должно быть
 ListBox2.Items.Add(FloatToStr(PR.F2)); // 2, как и должно быть
 ListBox2.Items.Add(IntToStr(SizeOf(PR))); // 20, как и должно быть
end;


 
Юрий Зотов ©   (2009-07-01 08:33) [7]

Вообще-то, для всех было бы полезно эту странность обсудить. Завел ветку:
http://delphimaster.net/view/15-1246422749/


 
oxffff ©   (2009-07-01 08:54) [8]


> В D7 все работало нормально, т.е. операторы вида
>
> Mix.N2 := 0.7809 и Mix.Сomp[0] := 0.7809 эавивалентны.


Я не еще не запускал Delphi 2009. Но первое что бросилось в глаза это
Сomp[0] и

True  : (Comp : array[1..7] of Extended);
 end;

?


 
brother ©   (2009-07-01 09:09) [9]

> Вообще-то, для всех было бы полезно эту странность обсудить.
> Завел ветку:
> http://delphimaster.net/view/15-1246422749/

тогда эту закрыть не мешало бы...


 
MBo ©   (2009-07-01 09:17) [10]

D2006, Align 8


type
TRec1 = record
  case boolean of
    False : (F1: Extended; F2: extended);
    True  : (A : array[1..2] of extended);
end;
TRec2 = record
  case boolean of
    False : (F1, F2: extended);
    True  : (A : array[1..2] of extended);
end;
TPackRec = packed record
  case boolean of
    False : (F1: Extended; F2: extended);
    True  : (A : array[1..2] of extended);
end;
var
 R1: TRec1;
 R2: TRec2;
 PR: TPackRec;
begin
 Memo1.Lines.Add(Format("R1 Size %d F2 Offset %d  A2 Offset %d",[SizeOf(R1), Integer(@R1.F2) - Integer(@R1), Integer(@R1.A[2]) - Integer(@R1)]));
 Memo1.Lines.Add(Format("R2 Size %d F2 Offset %d  A2 Offset %d",[SizeOf(R2), Integer(@R2.F2) - Integer(@R2), Integer(@R2.A[2]) - Integer(@R2)]));
 Memo1.Lines.Add(Format("PR Size %d F2 Offset %d  A2 Offset %d",[SizeOf(PR), Integer(@PR.F2) - Integer(@PR), Integer(@PR.A[2]) - Integer(@PR)]));

вывод
R1 Size 32 F2 Offset 16  A2 Offset 10
R2 Size 24 F2 Offset 10  A2 Offset 10
PR Size 20 F2 Offset 10  A2 Offset 10


разница в смещении поля F2 между R1 и R2 объясняется этим:

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.


 
Юрий Зотов ©   (2009-07-01 09:44) [11]

> MBo ©   (01.07.09 09:17) [10]

Да, это объясняет поведение в D7 - но в D2009, видимо, сделано иначе.


 
Anatoly Podgoretsky ©   (2009-07-01 09:49) [12]

> Чайник  (30.06.2009 21:15:01)  [1]

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


 
Юрий Зотов ©   (2009-07-01 10:50) [13]

> MBo ©   (01.07.09 09:17) [10]

Кстати, и поведение в D7 тоже не совсем объясняет (SizeOf = 24).


 
Sapersky   (2009-07-01 11:57) [14]

Кстати, и поведение в D7 тоже не совсем объясняет (SizeOf = 24).

Finally, the compiler rounds the total size of the record upward to the byte boundary specified by the largest alignment of any of the fields.

У Extended выравнивание - 8.
В хелпе D5, кстати, написано что 2. Тем не менее, в примере [10] все результаты совпадают с 2006-м (т.е. реально 8).


 
vuk ©   (2009-07-01 12:19) [15]

Собственно, объявление записи как packed от бага избавляет. А вообще, на будущее, видимо, стоит попробовать для записей пользоваться не вариантными секциями, а свойствами.


 
Чайник ©   (2009-07-01 23:58) [16]


> Anatoly Podgoretsky ©   (01.07.09 09:49) [12]
> Ты чего то не договариваешь,
>  не сообщаешь какой то важной информации.Для указаного случая
> не важно packed или нет, разница может проявляться только
> при использование низкоуровневых методов доступа и при импорте/экспорте


Да нет, ничего особенного не использую:

function GetAthmosphere(const T, P: Extended; MKind : TtcMixtureKind): TtcMixture;
var tmpMix : TtcMixture;
begin
 tmpMix.Name := "Сухой воздух";
 tmpMix.MixtureKind := thpVolumeProcent;
 tmpMix.N2  := 0.7809;
 tmpMix.Ar  := 0.0093;
 tmpMix.O2  := 0.2095;
 tmpMix.H2O := 0.0;
 tmpMix.CO  := 0.0;
 tmpMix.CO2 := 0.0003;
 tmpMix.CH4 := 0.0;
 Result := tmpMix;
end;
...
...
   for i:=1 to N_COMP do begin
      FGasProp.grdMix.Cells[0,i] := aMixName[i];
      FGasProp.grdMix.Cells[1,i] := FloatToStr(tmpMix.Comp[i]);
   end;


Кстати, посмотрел в настройки - действительно, в D7 стоит Record Field Alignment=8, а в D2009 - QuadWord.
Но! Перепробовал все возможные предлагаемые варианты (QWord, DWord, Word, Byte)- ничего не помогает, баг остается.


 
Германн ©   (2009-07-02 00:42) [17]


> Юрий Зотов ©   (01.07.09 09:44) [11]
>
> > MBo ©   (01.07.09 09:17) [10]
>
> Да, это объясняет поведение в D7 - но в D2009, видимо, сделано
> иначе.
>

Может Борис скажет где в документации на Д2006 есть те строки, которые он привел в конце своего поста. А автор (или ещё кто, у коно есть Д2009) посмотрит что написано в таком же месте в документации на Д2009. Тогда будет ясно баг это или новое правило.


 
Германн ©   (2009-07-02 00:49) [18]


> vuk ©   (01.07.09 12:19) [15]
>
> Собственно, объявление записи как packed от бага избавляет.
>  А вообще, на будущее, видимо, стоит попробовать для записей
> пользоваться не вариантными секциями, а свойствами.

Для некоторых новых проектов это наверно подойдёт.
Для некоторых проектов (неважно старых или новых) это не подойдёт никогда. Имхо.
А проблемы с переносом старых проектов на новые версии Дельфи всё равно останутся.


 
MBo ©   (2009-07-02 04:23) [19]

>Может Борис скажет где в документации на Д2006 есть те строки, которые он привел в конце своего поста

в хелпе Index-Look for -  packed - Record types reference - часть Record Types в топике Internal Data Formats

напрямую темы Internal Data Formats и Record Types в хелпе 2006 не ищутся
Internal Data Formats


 
Чайник ©   (2009-07-02 10:08) [20]

А вот что написано в хелпе 2009 (обратите внимание на последнюю фразу):

To ensure proper alignment of the fields in an unpacked record type, the compiler inserts an unused byte before fields with an alignment of 2, and up to three unused bytes before fields with an alignment of 4, if required. Finally, the compiler rounds the total size of the record upward to the byte boundary specified by the largest alignment of any of the fields.

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.

When a record type is declared in the {$A-} state, or when the declaration includes the packed modifier, the fields of the record are not aligned, but are instead assigned consecutive offsets. The total size of such a packed record is simply the size of all the fields. Because data alignment can change, it"s a good idea to pack any record structure that you intend to write to disk or pass in memory to another module compiled using a different version of the compiler.


 
MBo ©   (2009-07-02 12:11) [21]

угу, в 2006 то же самое



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

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

Наверх




Память: 0.52 MB
Время: 0.005 c
15-1263202280
Игорь
2010-01-11 12:31
2010.03.28
Драйвер под Windows 7


15-1262726623
tmtlib
2010-01-06 00:23
2010.03.28
Компилятор в EXE на Delphi с исходниками.


6-1215513539
kolj
2008-07-08 14:38
2010.03.28
Передача файла через HTTP протокол


3-1220515408
DVM
2008-09-04 12:03
2010.03.28
ID последней добавленной записи


15-1263079904
Германн
2010-01-10 02:31
2010.03.28
Скончался автор "Ежика в тумане" Сергей Козлов





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский