Notes |
|
(0006426)
|
zed
|
13-04-2012 07:35
|
|
Похоже, что утечки появились из-за глобальной расстановки const у интерфейсных параметров.
К примеру, при такой передаче интерфейса в функцию:
TEnumDoublePointLonLatToMapPixel.Create(
AProjection.Zoom,
AProjection.GeoConverter,
TEnumLonLatPointFilterFirstSegment.Create(
AEnum
)
)
получаем Memory Leak: Type=TEnumLonLatPointFilterFirstSegment; |
|
|
(0006427)
|
vdemidov
|
13-04-2012 08:41
(edited on: 13-04-2012 08:42) |
|
Даже не знаю, что с этим делать.
Убирать Const как-то некрасиво. А заводить локальную переменную на каждый такой конструктор странно.
|
|
|
(0006429)
|
zed
|
13-04-2012 10:52
|
|
The only issue I know of with the const interface format is as follows:
procedure DoSomething(i:Inknown);
begin
end;
procedure DoSomethingConst(const i:Inknown);
begin
end;
procedure DoSomethingConst2(const i:Inknown);
begin
DoSomething(i);
i.DoSomethingElse; //1
end;
procedure Main;
var
o1:TInterfacedObject;
begin
o1 := TInterfacedObject.Create;
//2
DoSomething(o1);
//3
o1.DoSomethingElse;
o1 := TInterfacedObject.Create;
//4
DoSomethingConst(o1);
o1.DoSomethingElse; //Succeeds
o1.Free; //Required
At //2 the Compiler automatically adds an AddRef before calling the
procedure and a _Release after which in turn calls Destroy
//3 Fails because o1 has been destroyed.
At //4 the Compiler does not do AddRef or _Release calls so Destroy is
never called.
Of course this can be hidden:
DoSomething( TInterfacedObject.Create);
The object is released after the call
DoSomethingConst( TInterfacedObject.Create);
The object is not released after the call and there is a memory leak.
DoSomethingConst2( TInterfacedObject.Create);
The object is unexpectedly released after the call to DoSomething and
line //1 fails. |
|
|
(0006430)
|
zed
|
13-04-2012 10:54
|
|
Так что const у интерфейсов нужно расставлять очень осторожно.
Сейчас показывает утечку даже здесь:
function TLonLatPolygonLine.GetEnum: IEnumLonLatPoint;
begin
Result := TEnumDoublePointBySingleLonLatLine.Create(Self, True, @FPoints[0], FCount);
end;
Memory Leak: Type=TEnumDoublePointBySingleLonLatLine |
|
|
|
Оно то так. Но ведь если внутри DoSomethingConst будет присваивание в глобальную переменную, то все должно быть нормально. Тоесть объект удалится после обниливания глобальной переменной. А в нашем случае этого не происходит. |
|
|
|
Простейший пример:
type
TTestObj = class
private
FI: IInterface;
public
constructor Create(const AI: IInterface);
end;
{ TTestObj }
constructor TTestObj.Create(const AI: IInterface);
begin
FI := AI;
end;
var
VObj: TTestObj;
begin
try
VObj := TTestObj.Create(TInterfacedObject.Create);
VObj.Free;
except
on E:Exception do
Writeln(E.Classname, ': ', E.Message);
end;
end.
Все нормально никаких утечек.
Блин. Я кажись понял в чем дело. |
|
|
(0006433)
|
zed
|
13-04-2012 11:26
|
|
Т.е. в этом конкретном случае внутрях небыло присвоения интерфейса? |
|
|
|
Ага. Именно. Было просто использование Enum-а. |
|