Thema: Delphi Objekt freigeben

Einzelnen Beitrag anzeigen

jottkaerr

Registriert seit: 2. Jul 2007
Ort: Tuttlingen
80 Beiträge
 
Delphi 10.1 Berlin Professional
 
#6

Re: Objekt freigeben

  Alt 22. Jun 2008, 12:25
Auch wenn Du inzwischen die Methode GetAutoByName() als Schuldigen ausgemacht und korrigiert hast, stecken im folgenden Code noch zwei Fehler.

Zitat von Yheeky:
Delphi-Quellcode:
var tempAuto : TAuto;
begin
tempAuto := TAuto.Create;
tempAuto := autoSammlung.GetAutoByName('Opel');

try
  idHTTP.Get('...');
finally
  tempAuto.Free;
end;

end;
Zum einen erzeugst Du ein TAuto, aber die einzige Referenz auf dieses Objekt überschreibst Du in der nächsten Zeile sofort wieder. Somit hast Du ein Speicherleck.

Der zweite Fehler ist noch viel schwerwiegender und kann im weiteren Verlauf zu einer Zugriffsverletzung oder Ähnlichem führen. Über GetAutoByName() lässt Du dir eine Referenz auf ein Objekt geben, das Du später freigibst, ohne dass die autoSammlung etwas davon erfährt (ich gehe mal davon aus, dass sich das Objekt im Destruktor nicht bei autoSammlung abmeldet). Bei einem späteren Aufruf von GetAutoByName() kann es passieren, dass versucht wird, auf dieses nicht mehr existierende Objekt zuzugreifen (z.B. für den Namensvergleich). Und wenn autoSammlung sich auch um das Freigeben der von ihr verwalteten Objekte kümmert, wird sie irgendwann später den Destruktor ein zweites Mal aufrufen -- und dadurch in nicht mehr alloziertem Speicher wildern.

Und selbst wenn sich das TAuto-Objekt im Destruktor sauber bei autoSammlung abmeldet: Du wirst nach dem Ausführen des obigen Codes keinen Opel mehr in der Sammlung finden. Das dürfte wahrscheinlich nicht gewünscht sein.

Beheben kannst Du beide Probleme, indem Du entweder eine methode TAuto.Assign einführst, die die Propertys eines anderen TAuto-Objekts übernehmen kann:

Delphi-Quellcode:
var tempAuto : TAuto;
begin
  tempAuto := TAuto.Create;

  try
    tempAuto.Assign(autoSammlung.GetAutoByName('Opel'));
    idHTTP.Get('...');
  finally
    tempAuto.Free; // <-- auch hier der Fehler
  end;

end;
Oder Du verzichtest auf die Freigabe, denn autoSammlung kümmert sich (hoffentlich) selbst darum:

Delphi-Quellcode:
var tempAuto : TAuto;
begin
  tempAuto := autoSammlung.GetAutoByName('Opel');

  idHTTP.Get('...');
end;
Jürgen Krämer
Sometimes I think the surest sign that intelligent life exists elsewhere
in the universe is that none of it has tried to contact us. (Calvin)
  Mit Zitat antworten Zitat