Seite 1 von 2
[gelöst] Löschen von Objekten, die in einer QList sitzen
Verfasst: 7. November 2007 07:46
von bw1faeh0
Guten Morgen,
ich habe mit meiner Anwendung das Problem, dass sie, je länger sie läuft, immer mehr Speicher benötigt.
Ich denke, dass es mit einer QList zu tun hat, die ich zur Kommunikation zwischen zwei threads nutze.
Folgendes Prinzip habe ich implementiert:
Code: Alles auswählen
Thread 1:
while(1)
{
p_item = new eine_neue_Variable
// tu was mit der neuen Variable
// zum Schluss:
meine_QList->append(p_item);
}
Thread 2:
while(1)
{
if (!meine_QList->isEmpty())
{
emit data(meine_QList->first());
meine_QList->removeFirst();
}
}
meine_QList ist dabei natürlich beiden Threads bekannt. Das ganze funktioniert auch zufriedenstellend.
Meine Vermutung: Die Variablen werden zwar von der Liste gelöscht, verbleiben jedoch im Speicher.
Ist die Vermutung korrekt?
Wie kann ich das Problem lösen?
Ganz naiv habe ich es mit
probiert, aber das mag der Kompiler auch nicht
Grüße
Christian
Verfasst: 7. November 2007 08:28
von bw1faeh0
Scheinbar habe ich das/ein Problem dabei gefunden.
Ich erzeuge ja bei jedem Durchlauf der while(1) im Thread 1 mit new eine neue Variable. Dies habe ich gemacht, da ich dachte, dass QList::append() nur eine Adresse des List-Objekts speichert. Aber scheinbar speichert es eine Kopie.
Ich habe den Code nun so umgeschrieben:
Code: Alles auswählen
Thread 1:
while(1)
{
p_item = new eine_neue_Variable ;
// tu was mit der neuen Variable
// zum Schluss:
meine_QList->append(p_item);
delete p_item;
}
Thread 2 ist gleich geblieben. Die Funktion der Software scheint auch nicht eingeschränkt zu sein. Ich hoffe, dass dies nicht an meinen Testdaten liegt. Das muss ich noch testen.
Ist obige Annahme von mir korrekt? Wird da eine Kopie und keine Referenz in der Liste gespeichert?
Verfasst: 7. November 2007 08:32
von Christian81
Ich würde sagen wir brauchen hier ein bischen C++ Grundwissen...
p_item is ein Pointer. Wenn Du es ihn delete löscht ist auch das Objekt daran weg... also ist deine zweite Antwort falsch.
Und dein erstes Problem liegt daran dass Du dort den Pointer nicht mehr löschst.
Re: Löschen von Objekten, die in einer QList sitzen
Verfasst: 7. November 2007 08:39
von DarkWotan
bw1faeh0 hat geschrieben:
Ganz naiv habe ich es mit
probiert, aber das mag der Kompiler auch nicht

Was mag er denn nicht? Gebt uns Fehlermeldungen, mit booleschen Aussagen wie "geht nicht" kann man wenig anfangen.
MfG, Cedric
Verfasst: 7. November 2007 08:44
von Christian81
Ach nochwas
Code: Alles auswählen
while(1)
...
[/while]
ist nicht sehr gut - ausser du hast zu viel Rechenpower... :)
Probiere es mit Signals/Slots um solche busy waits zu vermeiden.
Verfasst: 7. November 2007 08:45
von bw1faeh0
Christian81 hat geschrieben:
p_item is ein Pointer. Wenn Du es ihn delete löscht ist auch das Objekt daran weg... also ist deine zweite Antwort falsch.
Ich will das Objekt ja auch löschen, nach dem ich es der Liste anghängt habe.
Ich kann doch nur delete mit Objekten machen, die ich mit new erzeugt habe, oder?
Christian81 hat geschrieben:
Und dein erstes Problem liegt daran dass Du dort den Pointer nicht mehr löschst.
Ich denke, dass ich das doch nun mache...?
Code: Alles auswählen
VariablenTyp * p_item;
p_item = new VariablenTyp;
// mach was damit
my_Qlist->append(p_item);
delete p_item;
// pointer auf ein definiertes Ziel zeigen lassen
p_item = 0;
Du hast mich jetzt verwirrt...
Verfasst: 7. November 2007 08:46
von Christian81
Wenn Du es löschst, wie willst Du dann im zweiten Thread noch auf die Klasse zugreifen wo du sie doch gelöscht hast? C++ Grundlagen!
Verfasst: 7. November 2007 08:48
von bw1faeh0
Mein Rechner hat viel Rechenpower
Der berechnet die while(1) in 6 Minuten
Nein, im Ernst: natürlich nehme ich Signals und Slots sowie einen Timer, der alle 10ms das ganze aufruft.
Die Fehlermeldung des Kompilers zu "delete meine_List->first();" lautet:
Kompiler Joe hat geschrieben:
FmbSniffer.cpp: In member function `void SendThread::readData()':
FmbSniffer.cpp:250: error: type `struct FmbData' argument given to `delete', expected pointer
Verfasst: 7. November 2007 08:51
von bw1faeh0
Christian81 hat geschrieben:Wenn Du es löschst, wie willst Du dann im zweiten Thread noch auf die Klasse zugreifen wo du sie doch gelöscht hast? C++ Grundlagen!
In dem append keine Adresse speichert, sondern eine Kopie des Objektes anlegt. Das dachte ich zumindest. Und scheinbar geht es ja auch...
Thread 1 wird alle 10ms aufgerufen und macht die new/append/delete Aktion.
Thread 2 wird alle 100ms aufgerufen und plottet mir den Inhalt der Liste... und da kommen immer 10 neue Datensätze auf dem Plotter raus...
soweit, wie ich das bisher beurteilen kann.
Verfasst: 7. November 2007 08:52
von Christian81
Du zeigst uns zu wenig Code.
Wie hast Du deine QList<> erzeugt? So wie es aussieht einfach mit QList<myStruct>. Aber warum verwendest Du dann new? Wie gesagt - C++ Grundlagen fehlen hier wohl

Verfasst: 7. November 2007 09:02
von bw1faeh0
Ok, dann hier mehr Code:
das Struct sieht wie folgt aus:
Code: Alles auswählen
/*
* Typedef für die Daten eines empfangenen Telegramms
*/
typedef struct
{
bool inUse;
union
{
unsigned char BYTE; // Byte-Zugriff
struct
{
unsigned char RESERVIERT7: 1;
unsigned char SENDEN: 1;
unsigned char RESERVIERT5: 1;
unsigned char RESERVIERT4: 1;
unsigned char RESERVIERT3: 1;
unsigned char FILTERBEREIT: 1;
unsigned char RICHTUNG: 1;
unsigned char KANAL: 1;
}Bit; // Bit-Zugriff
}Status;
BYTE checksum;
WORD laenge;
TIME zeit;
struct
{
union
{
unsigned char BYTE;
struct
{
unsigned char RESERVIERT: 1;
unsigned char ASABIT: 1;
unsigned char SWADRESSE: 3;
unsigned char HWADRESSE: 3;
}Bit;
}Teilnehmer;
QList<unsigned char> NUTZDATEN;
}FM_Data;
}FmbData;
hier die Erzeugung der QList:
Im Konstruktor:
Diese Liste wird dann an die beiden Threads übergeben, die jeweils in einer eigene Klasse implementiert sind.
Ich erzeuge mit new dann neue Variablen vom Typ FmbData, da ich zum Zeitpunkt der Implementierung nicht weiß, wieviele Variablen ich benötige und deswegen keine feste Anzahl angeben kann.
Das mit new zu erledigen habe ich aus einer Vorlesung, in der es um Objektorientierung geht.
Verfasst: 7. November 2007 09:06
von Christian81
Dann kann das hier
Code: Alles auswählen
p_item = new eine_neue_Variable ;
// tu was mit der neuen Variable
// zum Schluss:
meine_QList->append(p_item);
Nie und nimmer funktionieren...
Also entweder erzeuge ich ein paar Pointer, speichere die
Pointer in der QList oder ich möchte die komplette Struktur in der QList speichern und erzeuge demnach keine Pointer mit new.
Verfasst: 7. November 2007 09:16
von bw1faeh0
Ok, dann schreibe ich mal, was ich machen wollte:
Ich will mir Variablen der Struktur erzeugen und diese in der Liste speichern.
p_item will ich nur als temporären zeiger nutzen, um auf die neu erzeugten variablen zugreifen zu können und sie mit Inhalt zu füllen und die neue Variable danach in die Liste zu schieben.
Wie sollte ich das anders machen?
Verfasst: 7. November 2007 09:31
von bw1faeh0
achherje... mir ist grad noch ein kleiner, aber sicher nicht unwichtiger Punkt aufgefallen, den ich vergessen habe...
Code: Alles auswählen
mutex->lock();
telegramList->append(*newTelegram);
mutex->unlock();
delete newTelegram;
Wenn ich das richtig sehe, dann Speichere ich immer den Inhalt meiner Variabeln in der Liste, oder?
Verfasst: 7. November 2007 09:35
von Christian81
Code: Alles auswählen
mutex->lock();
telegramList->append(*newTelegram);
mutex->unlock();
delete newTelegram;
Du weisst schon dass Du hier jetzt zweimal eine Struktur mit new erzeugst (und beide male ein Memleak)?
Wie ich schon sagte - entweder
Code: Alles auswählen
QList <myStruct*> l;
l.append(new myStruct);
...
delete l.first();
oder
Code: Alles auswählen
QList<myStruct>
myStruct a;
l.append(a)
...
// keine delete (da ja auch kein new)