Ниже приведен очень простой фрагмент кода, который имитирует структуру класса в моем коде (форма содержит только одну кнопку, прикрепленную к событию click). Я использую Delphi XE и XE II и вижу неприятные сбои при уничтожении объектов в моем производственном коде, на котором основан этот класс. Эти сбои происходят только в том случае, если я разрешу инициализировать элементы элемента массива в TMyClass в методе Clear ().
К сожалению, до сих пор сбой не повторяется в этом примере кода, но он имитирует очень странное поведение с размером экземпляров, которое, как я подозреваю, может быть причиной проблемы.
Если я помещу точку останова в функцию TMyClass.Clear и посмотрю на члена InstanceSize отчетов о классе 1288. Это странно, поскольку размер одного члена массива действительно составляет 12 КБ. Я могу изменить предоставляемый тип с TRecord2 на Integer, и я получаю тот же результат InstanceSize. Если я полностью удаляю массив из класса, я получаю размер экземпляра ~ 264 байта, что кажется чрезмерным для класса, который содержит только один экземпляр записи размером 128 байт. Это указывает на то, что компилятор выделил 1024 байта для хранения массива для члена V (типа TT) в TMyClass.
Я подозреваю, что странный размер экземпляра вызывает плохие вещи, когда я записываю 12 КБ данных в объект, размер которого, по мнению компилятора, составляет 1 КБ.
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
type
TRecord = record A : Array[1..128] of byte; end;
TRecord2 = packed record S : Single; T : TDateTime; end;
TBase = class(TObject)
public
R : TRecord;
end;
TBase2<T> = class(TBase)
public
type
TT = packed array [0..31, 0..31] of T;
var
V : TT;
R2 : TRecord;
end;
TMyClass = class(TBase2<TRecord2>)
public
procedure Clear;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
O : TMyClass;
begin
O := TMyClass.Create;
O.Clear;
O.Free;
end;
{ TMyClass }
procedure TMyClass.Clear;
var
i, j : integer;
begin
for i := 0 to 31 do
for j := 0 to 31 do
begin
V[I, J].S := 0;
V[I, J].T := 0;
end;
end;
end.