![]() |
Problem beim zerstören von Instanz
Hallo!
Ich hab ein Problem beim zerstören von Instanzen beim Beenden des Programms! Und zwar habe ich eine Reihe von Instanzen einer Klasse x. In dieser Klasse x befindet sich eine Variable, die auf eine Instanz der Klasse y zeigt. Am Ende des Programms durchlaufe ich alle Instanzen der Klasse x und schaue mittels assigned, bevor ich sie zerstöre, ob in der Variable noch eine Instanz der Klasse y besteht. Bringt mir das true, wird auch die Instanz von y zerstört. Doch jetzt zum Problem: Wenn ich zur Laufzeit bereits durch eine andere Methode die Instanz von y zerstört habe, liefert mir assigned trotzdem true und wenn ich dann die Instanz zerstören will, kommt es zur Exception: der Klasse EConvertError Format '%p' ungültig oder nicht kompatibel mit Argument. Woran könnte das liegen? Das wird durchlaufen:
Delphi-Quellcode:
Damit zerstöre ich es während der Laufzeit in einem anderen Formular:
for i := length(zimmerObj)-1 downto 0 do
begin if assigned(zimmerObj[i].buchung) then begin if assigned(zimmerObj[i].buchung.kunde) then begin zimmerObj[i].buchung.kunde.Free; end; zimmerObj[i].buchung.Free; //Hier nach kommt der Fehler end; zimmerObj[i].Free; end;
Delphi-Quellcode:
myZimmer.buchung.kunde.Free;
myZimmer.buchung.Free; |
Re: Problem beim zerstören von Instanz
Moin Stoermi,
da Du in dem Falle wohl nicht FreeAndNil verwenden kannst, sollest Du nach dem .Free noch ein := nil hinzufügen. Dann klappt auch Assigned. |
Re: Problem beim zerstören von Instanz
Man muß beim Anwenden von Free gar nicht nachfragen ob die Variable zugewiesen ist oder nicht. Folgendes führt zu keinem Fehler:
Delphi-Quellcode:
Das liegt daran, dass Free eine Klassenfunktion ist. Bei Dir tritt ein Fehler auf, weil Du
sl := TStringList.Create;
sl.Free; // gibt die StringList frei. sl ist hinterher NICHT nil, sondern zeigt ins leere sl.Free; // funktioniert trotzdem!
Delphi-Quellcode:
aufrufst - das funktioniert nur wenn buchung nicht ins Leere zeigt und nicht nil ist. (Der Fehler ist also nicht das Free, sondern das buchung.kunde - buchung zeigt ins nirvana und kunde ist dort nicht zu finden)
buchung.kunde.Free;
Immer beachten: Ein Zeiger / eine Klasse die man noch braucht sollte man nach dem Aufruf von Free immer auf nil setzen, damit man an anderer Stelle weiß ob sie auf einen Wert zeigt oder nicht. Das kann man entweder mit zwei Befehlen machen (sl.Free; sl := nil;) oder mit FreeAndNil(sl). Frage: Warum programmierst Du nicht objektorientiert und gibst den Kunden im Destruktor der Buchung automatisch frei? Dann reiche Buchung.Free; und den ganzen anderen Kram kannst Du dir schenken. |
Re: Problem beim zerstören von Instanz
Moin bttb930,
Zitat:
Es liegt daran, dass zwischen den Zugriffen der Speicher noch nicht anderweitig verwendet wurde, und somit noch das Objekt enthält. Das Ganze kann nämlich auch ebensogut auf einen Fehler auflaufen. |
Re: Problem beim zerstören von Instanz
Stimmt, Free ist tatsächlich keine Klassenfunktion.
Free ist allerdings nicht virtuell, und DAS ist der Grund warum man statt
Delphi-Quellcode:
auch einfach
if self <> nil then
self.Free;
Delphi-Quellcode:
aufrufen kann, denn selbst wenn self = nil ist, findet der Compiler die Funktion Free, da sie nicht virtuell gelinkt wird, sondern statisch. Und Free prüft als erstes ob self = nil ist oder nicht.
self.Free;
Das Beispiel das ich oben geschrieben habe funktioniert (wie Christian schreibt) tatsächlich nur dann, wenn der Speicher noch nicht anderweitig überschrieben wurde, was einfach daran liegt dass nach dem ersten Free sl <> nil ist. Funktioniert also i.d.R. nicht, da davon ausgegangen werden muß, dass der Speicher in der Zwischenzeit überschrieben wurde. Danke für die Korrektur, Christian, sonst hätte ich meine fehlerhafte Theorie im Kopf behalten. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:09 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-2025 by Thomas Breitkreuz