Deinitialisierung von TList
-
Ist doch ganz einfach:
1. eine leere Unit anlegen, Template Quellcode reincopieren
2. die Template *.h in die .cpp/.h includieren, wo die TListe verwendet werden soll
3. Anwendungsbeispiele unter dem Punkt "Anwendung im Quellcode" betrachtenSo ein Template-Klasse ist auch nichts anderes als eine "normale" Klasse, mit dem Unterschied, das man verschiedene Datentypen mit einer Klasse verwalten kann.
Das Objekt, was mit der Liste verwaltet werden soll, kommt in Spitze Klammern:TListe<TBaustein> *BausteinListe; BausteinListe = new TListe<TBaustein>;
oder
TListe<TBeliebigerDatenTyp> *ListeMitBeliebigemDatentyp; ListeMitBeliebigemDatentyp = new TListe<TBeliebigerDatenTyp>;
alles weitere siehe Beispiele.
-
@F98:
So ich hab mir deine Deklaration von dem Template nochmal angeschaut.
Allerdings hab ich da gesehen, dass du im Endeffekt genau das Gleiche machst, wie ich's schon vorher (ein paar Beiträge vorher) versucht habe.
//Das Löschen
TDBListElem *DB = NULL;while (DBList->Count > 0)
{
DB = (TDBListElemDBList->Items[0];
DBList->Delete(0);
delete DB;
}
DBList->Clear(); // Kann man sich dann eigentlich sparen
delete DBList;N anderes Gutes hat dein Code aber. Ich hab ein bisschen eine Idee
davon, wie ein Template funktioniert. (Wäre vielleicht nicht schlecht, wenn du's ein bisschen sauberer darstellen würdest. ;))
Allerdings hilft mir das jetzt nicht bei meinem Problem weiter.
-
Maffe001 schrieb:
TDBListElem wird angemeckert.
Das Ding ist, dass CodeGuard bei allen TLists meckert...Was denn nun?
Meckert CodeGuard bei den TList-Objekten oder den TDBListElem-Objekten?
Bekommst Du eigentlich irgendwo beim delete Exceptions?
Hast Du schon mal versucht bei einem delete DBListElem reinzudebuggen?
Geht er da auch in den Destruktor?
Hast Du überhaupt einen Destruktor für DBListElem?Gruß,
Alexander
-
Da hab ich mich, wohl etwas missverständlich ausgedrückt.
Die Sache ist die, dass er alle TLists angemeckert hat, weil ich bei keiner die Deinitialisierung gemacht habe, wie wir vorhin. "Folglich meckert er natürlich alle TLists an." Klar ist, dass er dann die Elemente in den TLists meint.Zu TDBListElem: Wie ich schon sagte, ist TDBListElem eine Struktur. An die Liste übergebe ich ja einen Zeiger, der auf einen reservierten Speicherplatz in Form von TDBListElem zeigt. D.h. es gibt dann auch einen Destruktor für diese Elemente, nämlich delete. Oder liege ich da jetzt total falsch?
Ach ja, delete wird natürlich ausgeführt.
-
Maffe001 schrieb:
"Folglich meckert er natürlich alle TLists an." Klar ist, dass er dann die Elemente in den TLists meint.
Das ist mir nicht klar. TList verwaltet nur void*-Zeiger. Ob Du die Objekte, auf die
diese Zeiger verweisen per delete gelöscht hast, weiß CodeGuard gar nicht - die TList
übrigens auch nicht. Du kannst das ausprobieren, indem Du mal ein delete auf einen
dieser Zeiger machst und anschließend versuchst darauf zuzugreifen. Obwohl der Ver-
weis noch in der Liste ist, ist er nicht mehr gültig.
Was ich damit sagen will: Im Prinzip verwaltet TList eine Liste von long(?)-Werten,
die "zufällig" Zeiger auf Objekte sind.
Wenn CodeGuard ein nicht freigegebenes TList-Objekt anmeckert, dann meint er das auch.Maffe001 schrieb:
D.h. es gibt dann auch einen Destruktor für diese Elemente, nämlich delete. Oder liege ich da jetzt total falsch?
Ich würde sagen, ja, da liegst Du total falsch. Der Befehl delete ruft nur den De-
struktor auf. Dieser muß in Deiner Klasse deklariert und definiert sein.Gruß,
Alexander
-
Gut, wenn das so ist, dann muss es ja einen Weg geben, wie man den Speicher von Strukturen wieder freigibt.
Ich hab so'n bisschen das Gefühl, du haust da jetzt ein bisschen durcheinander. Wie ich schon sagte TDBListElem ist nur ne Struktur, keine Klasse. Und DBListElem ist ein Pointer auf einen reservierten Speicherraum.typedef struct { char DBName[50]; char StrZeit[30]; char EndZeit[30]; } TDBListElem; TDBListElem *DBListElem = new TDBListElem;
Bis jetzt bin ich immer davon ausgegangen, dass man Zeiger mit delete auch wieder löschen kann.
-
So ich muss jetzt los. Ich bin erstmal bis Dienstag nicht hier. Ich hoffe, ich kann am Dienstag mit euch auch nochmal rechnen. Vielleicht hat sich das Problem dann aber auch schon erledigt.
Thx, Maffe
-
Maffe001,
Maffe001 schrieb:
Also wenn ich das richtig sehe, dann ist das das Gleiche was ich auch mache nur kompakter und schöner.
nein, Deine for-next-Variante läßt TDBListElem-Objekte im Hauptspeicher stehen. Zähle einfach mal die delete's und vergleiche diese mit der Anzahl der Elemente in Deiner Liste. Alexanders Variante sieht korrekt aus.
-
dschensky schrieb:
Deine for-next-Variante läßt TDBListElem-Objekte im Hauptspeicher stehen.
Naja, er löscht sie nicht aus der Liste. Deswegen werden wohl doch alle TDBListElem-
Objekte gelöscht, allerdings sind dann verwaiste Einträge in der Liste.
Ich glaube nach wie vor, daß das Problem nicht die einzelnen Elemente sind, denn
diese werden - nach den Aussagen von Maffe001 - nicht von CodeGuard angemeckert.Gruß,
Alexander
-
Alexander Kempf schrieb:
...werden wohl doch alle TDBListElem-
Objekte gelöscht*aaargh*, hab mich verguckt (Kartoffeln auf den Augen).
@Maffe001: Ich nehme alles zurück.
-
So da bin ich wieder. Ich hab mir die ganze Geschichte nochmal angeschaut, bin aber leider nicht weitergekommen. Nochmal zur Zusammenfassung. Der Codeguard gibt nach wie vor folgendes zurück:
The object (0x....) was never deleted
.
.
The object (0x....)(size: 1028 bytes) was created with new
TDBHandle::DBs_to_List (char
.
.Wenn ich auf *TDBHandle::DBs_to_List (char ) doppelklicke, dann komme ich bei dem Eintrag DB = new TDBListElem raus.
Wie schon gesagt, wenn DB mit Werten gefüllt ist, dann wird er in eine TList mit Add eingetragen.
Zum Löschen der TList und der Elemente benutze ich folgende Methode:
while (DBList->Count > 0) { TDBListElem *DB = (TDBListElem *) DBList->Items [0]; DBList->Delete (0); delete DB; } delete DBList;
Tut mir leid, ich schein da einiges letzte Woche durcheinander gehauen zu haben.
-
Maffe001 schrieb:
Wenn ich auf *TDBHandle::DBs_to_List (char ) doppelklicke, dann komme ich bei dem Eintrag DB = new TDBListElem raus.
Zeig doch mal, was Du an der Stelle machst (Quellcode).
Hast Du schon mal überprüft, ob Du vielleicht irgendwelche TDBListElem-Objekte
erzeugst, die Du dann aber nicht der Liste hinzufügst?Gruß,
Alexander
-
Also grob gesagt, erzeuge ich mehrere Datenstrukturen, die Datenbanken widerspiegeln sollen, die ich über ein Request an MySql auslese. Die Stelle sieht so aus.
MYSQL_RES *Res = mysql_store_result (hDB); int NumZ = (int) mysql_num_rows (Res); if (NumZ != 0) { TList *DBList = new TList; MYSQL_ROW Zeile; int NumFlds = 0; TDBListElem *DB = NULL; NumFlds = mysql_num_fields (Res); while (Zeile = mysql_fetch_row (Res)) { DB = new TDBListElem; for (int zaehler1 = 0; zaehler1 < NumFlds; zaehler1++) { switch (zaehler1) { case 0: sprintf (DB->DBName, Zeile[zaehler1]); break; case 1: sprintf (DB->StrZeit, Zeile[zaehler1]); break; case 2: sprintf (DB->EndZeit, Zeile[zaehler1]); break; } } DBList->Add (DB); DB = NULL; delete DB; //ja, ich weiss die Stelle ist Quatsch. // ist mir auch gerade aufgefallen. } mysql_free_result (Res); } . . .
Du siehst also, dass keine Elemente übrig bleiben, die nicht eingefügt werden. Oder doch.
-
Ist das eine Methode? Falls ja, dann verstehe ich die Deklaration von DBList
innerhalb der Methode nicht so ganz.TList *DBList = new TList;
Allerdings würde ich dann verstehen, weshalb CodeGuard meckert.
Wenn das eine Methode ist und Du diese mehr als einmal aufrufst, könnte ich
ebenfalls verstehen, daß CodeGuard meckert - oder wird am Ende dieser Methode
alles gelöscht? Dann würde ich den Sinn für die Liste nicht verstehen...
Irgendwie verstehe ich den Zusammenhang noch nicht so genau...Gruß,
Alexander
-
Die Liste wird nur einmal erzeugt. Das Füllen der Liste geschieht in der while-Schleife.
Meinst du das? Wenn ich ehrlich bin verstehe ich jetzt auch nicht so ganz, was du meinst.
-
Zeig doch mal alles von der Erzeugung bis zum Löschen. Also, wenn Du das nicht
in einer Methode machst, wo dann? Wenn ja, zeig auch mal, wo und wie Du die
Methode aufrufst.Gruß,
Alexander
-
Die Erzeugung steht doch 2 Beiträge vorher schon. Oder meinst du die Erzeugung von TList etc.? Die kann ich dir nicht geben, weil TList ja schon ein vordefiniertes Objekt ist.
Die Erzeugung von TList geschieht halt mit:
TList *DBList = new TList; //Man könnte es auch so schreiben. TList *DBList = NULL; DBList = new TList;
Erklärt das jetzt deine Frage? Oder meinst du was ganz anderes?
-
Maffe001 schrieb:
Erklärt das jetzt deine Frage?
Nein. Wie ich schon sagte, fehlt mir ein bißchen der Zusammenhang.
Du zeigst nur immer ein paar Code-Zeilen, die die Erzeugung und das Füllen
der Liste mit ihren Elementen zeigt und ein paar Zeilen, die das Löschen
zeigen. Beide für sich sehen für mich eigentlich ganz in Ordnung aus, aber
es scheint ja doch irgendwo ein Fehler drinzustecken. Deshalb würde ich gerne
sehen, an welchen Stellen Du das Erzeugen/Löschen vornimmst.
Im Moment sieht es für mich so aus, als ob Dein Programm aus einem großen
monolithischen Block besteht, innerhalb dessen einmal eine Liste erzeugt und
gefüllt wird, um gleich darauf wieder auf die Elemente zuzugreifen und danach
alles wieder wegzuwerfen. Das würde mir aber nicht sehr sinnvoll erscheinen
und wahrscheinlich hast Du das auch nicht so gemacht (hoffentlich).Also, ich verwende Listen so, daß ich eine Klassenvariable vom Typ TList habe,
die im Konstruktor per new erzeugt wird. Andere Methoden meiner Klasse fügen
dieser Liste Objekte hinzu oder löschen sie auch wieder heraus (add/remove).
Im Destruktor der Klasse passiert dann das, was Du auch machst, nämlich alle
Elemente zu löschen und die Liste selbst auch.
Wenn Du die Liste auch so verwendest, dann zeig doch mal die entsprechenden
Methoden (inklusive Signatur) und die Aufrufe dieser Methoden. Vielleicht wird
dann der Zusammenhang für mich klarer.
Alles andere ist für mich Herumgestochere im Nebel.Gruß,
Alexander
-
Maffe001:
Vielleicht solltest du das Problem mal in einem (abstrakten) Minimalprojekt nachstellen, bei dem du ggf. auch den kompletten Code zwecks Nachvollziehen an andere weitergeben kannst.
Ausserdem lässt sich so prüfen, ob es sich um ein generelles Problem z.B. mit TList handelt oder ob der Fehler vielleicht doch irgendwo anders in deinem Hauptprogramm liegt.
-
Na gut, ich umreiße mal grob mein Vorhaben. Also es ist so, dass ich eine Anwendung schreibe, die in eine MySql-Datenbank die Daten von verschiedenen Messgeräten einträgt.
Für jede neue Messung wird eine neue DB angelegt, für jedes Messgeräte eine eigene Tabelle.
Um zu kontrollieren welche Messungen auf dem Rechner überhaupt "aktuell" sind, hab ich noch eine "globale" DB angelegt, die alle DB mit Namen, Startzeit und Endzeit abspeichert. So kann ich jetzt mit einem Vergleich von den vorhandenen DBs auf dem MySql-Server und den eingetragenen DBs in der globalen DB herausfinden, welche Messungen überhaupt noch vorhanden sind.
In meiner Arbeitsgruppe wurde entschieden, dass DBs, die nur auf dem Server aber nicht in der "globen" DB vorhanden sind und anders herum, nicht als Messung angesehen werden und somit auch nicht auf der graphischen Oberfläche angezeigt werden.Die Operationen der Anwendung auf MySql hab ich in einer eigenen Klasse (TDBHandle) gekapselt, so dass man die ganze Geschichte vielleicht auch noch mal woanders benutzen kann.
Der angesprochene Vergleich wird durchgeführt, wo die Liste angelegt wird, wenn die Initialisierungsfunktion (nicht der Konstruktor von TDBHandle) ausgeführt wird. Danach werden noch verschieden Operatioen auf diese Liste ausgeführt, wobei sie sich aber nicht mehr ändert.
Die angelegte Liste ist ein Mitglied von TDBHandle und soll dann im Destruktor von TDBHandle wieder glöscht werden.Ich weiss nicht, was ich noch schreiben soll. Alles was mit der Liste zu tun hat, steht schon in den Beiträgen weiter oben.
Wie gesagt, zwischen Erstellung und Löschen der Liste, geschehen nur noch Leseoperationen darauf.