SASGIS - SAS.Планета
View Issue Details
0001273SAS.Планета[All Projects] Багpublic12-04-2012 16:4610-10-2012 11:47
zed 
vdemidov 
normalminoralways
closedfixed 
WindowsXPSP3
.Nightly 
120808120808 
0001273: Утечка памяти в билде 5373 от 12.04.2012
Запускаем, ничего не трогаем. Закрываем -> утечка.
No tags attached.
? SASPlanet.Debug.elf (6,615) 12-04-2012 16:46
http://www.sasgis.org/mantis/file_download.php?file_id=748&type=bug
Issue History
12-04-2012 16:46zedNew Issue
12-04-2012 16:46zedFile Added: SASPlanet.Debug.elf
12-04-2012 16:47zedSummaryУтечка памяти в билде 5337 => Утечка памяти в билде 5373 от 12.04.2012
13-04-2012 07:35zedNote Added: 0006426
13-04-2012 08:41vdemidovNote Added: 0006427
13-04-2012 08:42vdemidovNote Edited: 0006427bug_revision_view_page.php?bugnote_id=6427#r3189
13-04-2012 10:52zedNote Added: 0006429
13-04-2012 10:54zedNote Added: 0006430
13-04-2012 11:01vdemidovNote Added: 0006431
13-04-2012 11:11vdemidovNote Added: 0006432
13-04-2012 11:19vdemidovStatusnew => resolved
13-04-2012 11:19vdemidovFixed in Version => 120808
13-04-2012 11:19vdemidovResolutionopen => fixed
13-04-2012 11:19vdemidovAssigned To => vdemidov
13-04-2012 11:26zedNote Added: 0006433
13-04-2012 11:46vdemidovNote Added: 0006434
14-05-2012 08:31vdemidovTarget Version => 120808
10-10-2012 11:47TolikStatusresolved => closed

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
(0006431)
vdemidov   
13-04-2012 11:01   
Оно то так. Но ведь если внутри DoSomethingConst будет присваивание в глобальную переменную, то все должно быть нормально. Тоесть объект удалится после обниливания глобальной переменной. А в нашем случае этого не происходит.
(0006432)
vdemidov   
13-04-2012 11:11   
Простейший пример:

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   
Т.е. в этом конкретном случае внутрях небыло присвоения интерфейса?
(0006434)
vdemidov   
13-04-2012 11:46   
Ага. Именно. Было просто использование Enum-а.