[gelöst] Löschen von Objekten, die in einer QList sitzen

Alles rund um die Programmierung mit Qt
bw1faeh0
Beiträge: 94
Registriert: 10. Oktober 2007 14:48
Wohnort: Braunschweig

[gelöst] Löschen von Objekten, die in einer QList sitzen

Beitrag 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

Code: Alles auswählen

delete meine_QList->first()
probiert, aber das mag der Kompiler auch nicht ;)

Grüße

Christian
Zuletzt geändert von bw1faeh0 am 7. November 2007 10:12, insgesamt 1-mal geändert.
bw1faeh0
Beiträge: 94
Registriert: 10. Oktober 2007 14:48
Wohnort: Braunschweig

Beitrag 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?
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag 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.
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
DarkWotan
Beiträge: 65
Registriert: 18. Mai 2006 10:03

Re: Löschen von Objekten, die in einer QList sitzen

Beitrag von DarkWotan »

bw1faeh0 hat geschrieben: Ganz naiv habe ich es mit

Code: Alles auswählen

delete meine_QList->first()
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
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag 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.
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
bw1faeh0
Beiträge: 94
Registriert: 10. Oktober 2007 14:48
Wohnort: Braunschweig

Beitrag 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...
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag 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!
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
bw1faeh0
Beiträge: 94
Registriert: 10. Oktober 2007 14:48
Wohnort: Braunschweig

Beitrag 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
bw1faeh0
Beiträge: 94
Registriert: 10. Oktober 2007 14:48
Wohnort: Braunschweig

Beitrag 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.
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag 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 :(
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
bw1faeh0
Beiträge: 94
Registriert: 10. Oktober 2007 14:48
Wohnort: Braunschweig

Beitrag 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:

Code: Alles auswählen

QList<FmbData>  *telegramList;
Im Konstruktor:

Code: Alles auswählen

telegramList = new QList<FmbData>;
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.
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag 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... :roll:

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.
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
bw1faeh0
Beiträge: 94
Registriert: 10. Oktober 2007 14:48
Wohnort: Braunschweig

Beitrag 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?
bw1faeh0
Beiträge: 94
Registriert: 10. Oktober 2007 14:48
Wohnort: Braunschweig

Beitrag 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?
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag 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)
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
Antworten