Неправильное распределение полей в объекте

Источник: delphikingdom
Дмитрий Орловский

Автор: Дмитрий Орловский, Королевство Delphi

КАТЕГОРИЯ 

КОМПИЛЯТОР.Неправильное распределение полей в объекте

ПРОДУКТ 

Delphi 7

ПЛАТФОРМА 

Windows


Класс TColumn описан в модуле DBGrid. Речь идет о поле FAssignedValues типа TColumnValues. Этот тип объявлен как set of TColumnValue и его размер равен 2 байтам. Согласно принятым правилам поле рассматриваемого типа должно выравниваться по четным адресам и иметь смещение +60. Тем не менее, оно имеет смещение +59, непосредственно примыкая к предыдущему однобайтовому полю. Результатом является значение TColumn.Instancesize=64, хотя при использовании декларируемого правилами выравнивания эта величина должна быть равна 68.

Тестовый код:

uses  DBGrids;
type  PColumnValues = ^TColumnValues;
var    obj: TColumn;
begin
  obj:=TColumn.Create(nil);
  Memo1.Lines.Clear;
//проверка смещения поля FAssignedValues:
  (PWord(Integer(obj)+59))^:=247; //устанавливаем FAssignedValues
  Memo1.Lines.Add(IntToStr(Word(obj.AssignedValues))); //читаем FAssignedValues
//для того чтобы метод чтения свойства Readonly возвращал в качестве
//значения FReadonly, нужно включить cvReadOnly в AssignedValues:
  (PColumnValues(Integer(obj)+59))^:=[cvReadOnly];
//проверка смещения поля FReadonly:
  (PByte(Integer(obj)+58))^:=1; //устанавливаем FReadonly
  Memo1.Lines.Add(IntToStr(Byte(obj.ReadOnly))); //читаем FReadonly
  obj.Free;
end;

Типовые решения При необходимости следует учитывать правильные смещения полей:

FField          +12
FFieldName      +16
FColor          +20
FWidth          +24
FTitle          +28
FFont           +32
FImeMode        +36
FImeName        +40
FPickList       +44
FPopupMenu      +48
FDropDownRows   +52
FButtonStyle    +56
FAlignment      +57
FReadonly       +58
FAssignedValues +59
FVisible        +61
FExpanded       +62
FStored         +63

Комментарий Компилятор нарушает утверждение, сделанное в справке по выравниванию полей в записях и классах:

 Type            Alignment
Set types	size of the type if 1, 2, or 4, otherwise 1 
Т.е., множество размером 2 байта по-умолчанию должно выравниваться на границу слова. Простим компилятору, это его личное дело, как выравнивать поля. Программист не ошибется, если будет обращаться к полям по имени, а не пытаться вычислить смещение вручную.
Каждому - свое.

Страница сайта http://test.interface.ru
Оригинал находится по адресу http://test.interface.ru/home.asp?artId=21095