svp писал(а):Или речь идёт об интерфейсах?
Да, о них самых )
Конкретнее:
Код: Выделить всё
type
IMemoryUser = interface(IInterface)
['{69856B39-CEC0-42F0-87EF-AE870FE20C0A}']
procedure free;
end;
IIndexElementsIterator = interface(IMemoryUser)
['{E512EC2B-16A5-4F38-A320-F7EB0777CCAC}']
procedure reset;
function hasNext: boolean;
function next: Int64;
end;
IIndexTreeElement = interface(IMemoryUser)
['{AA39ADC5-FB8B-4A9F-A6F3-87A5BA863222}']
function isExists(number: int64): boolean;
function isNotExists(number: int64): boolean;
function isNotExistsOnServer(number: int64): boolean;
procedure setExists(number: int64);
procedure setNotExists(number: int64);
procedure setNotExistsOnServer(number: int64);
function existsCount: Int64;
function notExistsOnServerCount: Int64;
function usedMemory: Int64;
procedure clear;
end;
Объект:
Код: Выделить всё
type
TIndexTreeElement = class(TInterfacedObject, IIndexTreeElement)
private
m_elements: TIndexElementsArray;
m_level: TTreeLevel;
m_iCoef: Int64;
m_iFirst: Int64;
constructor Create(first: Int64; coef: Int64; level: TTreeLevel);
function getSubTree(number: Int64; cr: boolean): IIndexTreeElement;
public
destructor Destroy; override;
function isExists(number: Int64): boolean;
function isNotExists(number: Int64): boolean;
function isNotExistsOnServer(number: Int64): boolean;
procedure setExists(number: Int64);
procedure setNotExists(number: Int64);
procedure setNotExistsOnServer(number: Int64);
function existsCount: Int64;
function notExistsOnServerCount: Int64;
function usedMemory: Int64;
procedure clear;
procedure free;
end;
Создаётся так:
Код: Выделить всё
function TIndexTreeElement.getSubTree(number: Int64; cr: boolean): IIndexTreeElement;
var
bl: word;
f: Int64;
begin
if Self = nil then raise MPEIllegalSelfState.Create
('TIndexTreeElement.getSubTree: Self is nil');
bl:= (number div m_iCoef) mod ElementsCount;
if (m_elements[bl] = nil) and cr then
begin
f:= m_iFirst + m_iCoef * bl;
case m_Level of
0: m_elements[bl]:= TIndexTreeElement.Create(f, Level1Coef, 1);
1: m_elements[bl]:= TIndexTreeElement.Create(f, Level2Coef, 2);
2: m_elements[bl]:= TIndexTreeElement.Create(f, Level3Coef, 3);
3: m_elements[bl]:= TIndexBitArray.Create(f);
end;
end;
Result:= m_elements[bl];
end;
методы раньше были написаны так:
Код: Выделить всё
procedure TIndexTreeElement.free;
begin
if Self <> nil then Self.Destroy;
end;
destructor TIndexTreeElement.Destroy;
begin
Self.Clear;
inherited;
end;
procedure TIndexTreeElement.clear;
var i: Integer;
begin
if Self = nil then exit;
for i := 0 to ElementsCount - 1 do
begin
if m_elements[i] <> nil then
m_elements[i].free;
end;
end;
и при попытке вызвать free на всё дерево при работе через интерфейс вылетал как водится 'отказ в доступе к памяти', если избывиться от интерфейсов всё отлично отрабатывало, если не избавляться и не вызывать free то при занулении ссылке на дерево память высвобождается.
Раньше обходился без интерфейсов, поэтому и не разбирался в их подробностях в дельфи (думаю это справедливо и для более ранних версий чем 2009).
Мне нужно знать подробности чтобы спроектировать так чтобы исключить утечку памяти.
Избавление от интерфейсов не выход, т.к. появляются лишние проверки.