![]() |
Objekt freigeben
Hi,
ich habe eben ziemlich lange über einem Problem gehangen, aber es inzwischen "gelöst". Folgende Sache tritt bei meinem Projekt auf: Ich habe ein eigenes Objekt von TObject abgeleitet (TDaten). Ich habe nun eine Funktion, die ein solches Objekt erstellt und Daten ins Internet sendet. Abschließend wollte ich das Objekt wieder freigeben, aber genau da kam ein Fehler.
Delphi-Quellcode:
Auch die Variante mit try...finally hat nicht funktioniert:
var tempAuto : TAuto;
begin tempAuto := TAuto.Create; tempAuto := autoSammlung.GetAutoByName('Opel'); idHTTP.Get('...'); tempAuto.Free; // <-- hier kommt eine Zugriffsverletzung. Wenn ich die Zeile rauslasse, funktioniert alles wie gewollt end;
Delphi-Quellcode:
Kann mir jemand erklären, woran die Zugriffsverletzung liegt?
var tempAuto : TAuto;
begin tempAuto := TAuto.Create; tempAuto := autoSammlung.GetAutoByName('Opel'); try idHTTP.Get('...'); finally tempAuto.Free; // <-- auch hier der Fehler end; end; |
Re: Objekt freigeben
Ein Wenig mehr Information bitte.
Wie sieht autoSammlung.GetAutoByName('Opel'); aus? Und was passiert bei idHTTP.Get('...'); ? Hinweise: Vermutlich kannst / musst Du Dir das "Create" und das "Free" sparen. Die Objekte existieren schon autoSammlung. tempAuto ist dann nur ein Verweis auf ein Element von autoSammlung. |
Re: Objekt freigeben
Danke für den kleinen versteckten Hinweis ;-) Habe den Fehler gerade gefunden. Es liegt tatsächlich in der Funktion GetAutoByName, obwohl mit hier beim Debuggen kein Fehler angezeigt wird!
Erklärung anhand eines Ausschnittes der Unit:
Delphi-Quellcode:
function TAuto.getAuto(Index: Cardinal): TAuto;
begin Result := TAuto(inherited Items[Index]); end; function TAuto.GetAutoByName(Autoname: String): TAuto: var I: Integer; tempAuto : TAuto; begin result := nil; if Count <> -1 then begin for I := 0 to Count - 1 do begin tempAuto := TAuto(getItem(I)); // <-- hier liegt der Fehler if tempAuto.Name = Autoname then begin result := tempAuto; Exit; end; end; end; end; Anstatt getItem, welches in der Basisklasse verfügbar ist, muss ich natürlich getAuto aufrufen. Dann funktioniert es auch! Danke nochmal für den Denkanstoss! Sehr ihr, manchmal muss man garnicht viel helfen ;-) |
Re: Objekt freigeben
Tach,
das Typecasting über
Delphi-Quellcode:
ist gefährlich. Besser wäre
TAuto(getItem(I))
Delphi-Quellcode:
weil es zur Exception kommt, wenn der Typ nicht stimmt.
:=getItem(I) as TAuto
Stefan |
Re: Objekt freigeben
Das sollte zwar relativ sicher sein, aber ist noch eine gute Ergänzung, danke!
|
Re: Objekt freigeben
Auch wenn Du inzwischen die Methode GetAutoByName() als Schuldigen ausgemacht und korrigiert hast, stecken im folgenden Code noch zwei Fehler.
Zitat:
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:
Oder Du verzichtest auf die Freigabe, denn autoSammlung kümmert sich (hoffentlich) selbst darum:
var tempAuto : TAuto;
begin tempAuto := TAuto.Create; try tempAuto.Assign(autoSammlung.GetAutoByName('Opel')); idHTTP.Get('...'); finally tempAuto.Free; // <-- auch hier der Fehler end; end;
Delphi-Quellcode:
var tempAuto : TAuto;
begin tempAuto := autoSammlung.GetAutoByName('Opel'); idHTTP.Get('...'); end; |
Re: Objekt freigeben
Zitat:
Aber ich wollte ihm halt nicht die komplette Lösung auf den Teller legen, sondern nur in die richtige Richtung schubsen. Anscheînend war der Schubser nicht stark genug. ;-) |
Re: Objekt freigeben
@RavenIV: Nein, leider war der Schubser nicht stark genug ;-)
Danke, für die Information. Ich weiss leider noch nicht so recht Bescheid über Objekte und konnte eueren Code auch leider noch nicht ganz nachvollziehen. Hatte mir mal ein Tutorial über Objekte und Objektlisten angeschaut, aber scheinbar habe ich noch lücken. Könnt ihr mir vielleicht nochmal einen kurzen Crash-Kurs geben? Wie ist das mit Referenzen, Speicherleck, wann muss ich Objekte mit Create initialisieren, wann darf ich sie mit Free freigeben, etc...? Wäre super! |
Re: Objekt freigeben
Objekte musst du mit Create initialisteren, wenn du dann diese Instanz verwenden willst. Willst du eine andere Instanz verwenden, wird diese einfach der anderen zugewiesen. Da sich Objekte wie Pointer verhalten, gibts dabei keine Probleme. Free brauchst du dann, wenn du das Objekt nicht mehr verwenden willst. Dies ist tödlich bei Objekten, die du von anderen Instanzen geholt hast, da dann auch die andere Instanz gelöscht wird.
Tipp nebenbei: Falls Free fehlschlägt, gibts ein Speicherleck. Nutze doch FreeAndNil(). Bernhard EDIT: Eigentlich gilt: Neue Frage, neues Thema |
Re: Objekt freigeben
Zitat:
@Fragesteller: mache für deine neue Frage bitte ein neues Thema auf. Das hat den Vorteil das du dem Thema entsprechend dem neuen Inhalt dann auch einen aussagekräftigen Titel geben kannst. Und das hat dann gleich wieder den Vorteil das man es über die Suche schneller findet wenn man das gleiche Problem hat. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 11:16 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz