C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Speicher frei geben
Goto page 1, 2  Next
 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ (German)
View previous topic :: View next topic  
Author Message
Shuo
Guest





PostPosted: Tue Sep 14, 2004 4:09 pm    Post subject: Speicher frei geben Reply with quote



Hallo zusammen,

ich habe ein kleines Problem. Naja..inzwischen entwickelt es sich zu
einem größeren Problem.
Folgendes:
Ich habe mehrere Funktionen, in denen mit new Speicher belegt wird.
Die Variabel, die hinter der Speicherbelegung steht, ist keine
globale. Rückgabewert ist ein int und Übergabe sind zwei Objekte.
Der Prototyp (mit teilcode) sieht also folgendermaßen aus:
int bla function(object a, object b)
{
.....
Klasse x = new x();
......

return 3;

}
Jetzt hab ich folgendes Problem. Ich muss diesen Speicher aus einer
anderen Klasse wieder frei geben.
Eine Globale Variabel wäre zwar ne Lösung, finde ich aber unschön. wie
kann ich aus einer anderen Funktion mit delete [] den Speicher von x
wieder freigeben? Ich könnte zwar den Prototypen ändern und die
Adresse mit übergeben, will aber nicht die Funktionen großartig
ändern.

Hat jemand einen Vorschlag?!

Mein Speicher läuft sonst über...:-)

Schöne Grüße!!!

--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
Back to top
Ozan Ayyüce
Guest





PostPosted: Tue Sep 14, 2004 5:15 pm    Post subject: Re: Speicher frei geben Reply with quote



Shuo:

Quote:
Klasse x = new x();

Jetzt hab ich folgendes Problem. Ich muss diesen Speicher aus einer
anderen Klasse wieder frei geben.

Wenn du die Implementation nicht grundsätzlich in Richtung RAII ändern
kannst solltest du einen smart-pointer benutzen, auto_ptr ist ein
einfacher:

http://www.gotw.ca/publications/using_auto_ptr_effectively.htm


Ozan

--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de

Back to top
Martin Gieseking
Guest





PostPosted: Tue Sep 14, 2004 5:17 pm    Post subject: Re: Speicher frei geben Reply with quote



[email]shuo (AT) gmx (DOT) at[/email] (Shuo) wrote in
news:de04b100.0409140809.3dec199c (AT) posting (DOT) google.com:

Quote:
Der Prototyp (mit teilcode) sieht also folgendermaßen aus:
int bla function(object a, object b)
{
....
Klasse x = new x();
.....

return 3;

}
Jetzt hab ich folgendes Problem. Ich muss diesen Speicher aus einer
anderen Klasse wieder frei geben.


Das sieht aber nicht nach gültigem C++ aus. Wahrscheinlich meinst Du in
etwa folgendes:

int bla (object a, object b) // ggf. Referenzen verwenden
{
...
Klasse *x = new Klasse;
...
return 3;
}


Was stellst Du denn in deiner Funktion mit dem erzeugten Objekt an?
Vermutlich wird es doch via Zeiger irgendwo in ein anderes Objekt
eingehängt oder anderweitig zugewiesen, so dass immer ein gültiger Zeiger
darauf existiert (den man zum Freigeben verwenden kann). Ggf. müsstest Du
das Problem noch etwas genauer beschreiben.



Quote:
Eine Globale Variabel wäre zwar ne Lösung, finde ich aber unschön. wie
kann ich aus einer anderen Funktion mit delete [] den Speicher von x
wieder freigeben?

Das oben erzeugte Objekt *x muss mit "delete x" freigegeben werden, nicht
mit "delete[] x".

Martin

--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de

Back to top
Boris Glawe
Guest





PostPosted: Tue Sep 14, 2004 5:40 pm    Post subject: Re: Speicher frei geben Reply with quote

Shuo wrote:
Quote:
Hallo zusammen,

ich habe ein kleines Problem. Naja..inzwischen entwickelt es sich zu
einem größeren Problem.
Folgendes:
Ich habe mehrere Funktionen, in denen mit new Speicher belegt wird.
Die Variabel, die hinter der Speicherbelegung steht, ist keine
globale. Rückgabewert ist ein int und Übergabe sind zwei Objekte.
Der Prototyp (mit teilcode) sieht also folgendermaßen aus:
int bla function(object a, object b)
{
....
Klasse x = new x();
//Das hier kann nicht gehen.

//das muss heißen
// Klasse *x = new Klasse();
Quote:
.....

return 3;

}
Jetzt hab ich folgendes Problem. Ich muss diesen Speicher aus einer
anderen Klasse wieder frei geben.

Da du das Objekt in der Methode erzeugst und einen int Wert zurückgbst, kann es
kaum sein, dass sich die Welt außerhalb deiner methode für das Objekt
interessiert. Ruf doch einfach delete x am Ende der methode auf !?

Quote:
Eine Globale Variabel wäre zwar ne Lösung, finde ich aber unschön. wie
kann ich aus einer anderen Funktion mit delete [] den Speicher von x
wieder freigeben? Ich könnte zwar den Prototypen ändern und die
Adresse mit übergeben, will aber nicht die Funktionen großartig
ändern.

Niemals mit globalen Variablen arbeiten! Deine Methoden garantieren den
zuverlässigen Zugriff auf Klassenmitglieder. Der Speicher der von
Klassenmitgliedern gebraucht wird, wird vom Destruktor wieder freigegeben.
Speicher der innerhalb einer Methode reserviert wird (wie in deinem Fall) wird
auch von der Methode wieder freigegeben. Einzgie Ausnahme:
Speicher eines Objektes, das von der Methode erzeugt *und* zurückgegeben wird,
wird nicht von der Klasse wieder freigegeben, sondern manuell von dem, der den
Aufruf der Methoden gemacht hat. Insbesondere werden solche erzeugte Objekte
niemals innerhalb der Klasse gespeichert (kenne zumindest kein sinnvolles
Beispiel).

Quote:

Hat jemand einen Vorschlag?!

Mein Speicher läuft sonst über...Smile

Man sollte Speicher immer freigeben, nicht erst, wenn der Speicher nicht mehr
reicht ;-)

Grüße Boris

--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de

Back to top
Martin Kaul
Guest





PostPosted: Tue Sep 14, 2004 5:47 pm    Post subject: Re: Speicher frei geben Reply with quote

Shuo wrote:
Quote:
Hallo zusammen,

ich habe ein kleines Problem. Naja..inzwischen entwickelt es sich zu
einem größeren Problem.
Folgendes:
Ich habe mehrere Funktionen, in denen mit new Speicher belegt wird.
Die Variabel, die hinter der Speicherbelegung steht, ist keine
globale. Rückgabewert ist ein int und Übergabe sind zwei Objekte.
Der Prototyp (mit teilcode) sieht also folgendermaßen aus:
int bla function(object a, object b)
{
....
Klasse x = new x();
Klasse *x = new x(); // oder ?
.....

return 3;

}
Jetzt hab ich folgendes Problem. Ich muss diesen Speicher aus einer
anderen Klasse wieder frei geben.
Eine Globale Variabel wäre zwar ne Lösung, finde ich aber unschön. wie
kann ich aus einer anderen Funktion mit delete [] den Speicher von x
wieder freigeben? Ich könnte zwar den Prototypen ändern und die
Adresse mit übergeben, will aber nicht die Funktionen großartig
ändern.

1. Möglichkeit:

von der Klasse "Klasse" gibt es nur ein einziges Objekt, dann
könntest du "Klasse" als ein Singleton realisieren und von jedem
Punkt deiner Applikation (d.h. dann auch von anderen Funktionen)
auf die konkrete Instanz zugreifen.

2. Möglichkeite:

es kann viele Instanzen/Objekte von "Klasse" geben, dann brauchst
du in irgend einer Form eine Verwalterklasse (die kann dann ein
Singleton sein), welche intern die Zeiger auf die Instanzen von
"Klasse" speichert (z.B. in ner Liste) und eine Zugriffsmethode auf
die konrete Instanz von "Klasse" gibt (d.h. suchen der Instanz in
der Liste und dann zurückgeben). Hierbei musst du aber jeder Instanz
von Klasse ne Kennung geben, weil du ja das konkrete Objektchen
identifizieren musst - oder du willst in deinen Funktionen
auf alle Instanzen von "Klasse" zugreifen, dann kann dein Verwalter
gleich die Liste rausgeben.

Der Eintrag der Instanz von "Klasse" in die Liste des Verwalters
kannst du gleich innerhalb des Konstruktors von "Klasse" machen -
und dann natürlich im Destruktor von "Klasse" dich wieder austragen.

Singleton ist ein Muster. Eine Beschreibung sollte eigentlich im
Netz gefunden werden können.

tschaule
Martin

--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de

Back to top
Steffen Rauh
Guest





PostPosted: Tue Sep 14, 2004 5:51 pm    Post subject: Re: Speicher frei geben Reply with quote

Quote:
Ich habe mehrere Funktionen, in denen mit new Speicher belegt wird.
[...]
Jetzt hab ich folgendes Problem. Ich muss diesen Speicher aus einer
anderen Klasse wieder frei geben.

Und warum musst du das? Das Objekt das du in deiner Funktion erzeugt hast,
scheint ja so unwichtig zu sein, dass niemand ausserhalb davon Kenntnis zu
haben braucht. Warum zerstörst du's nicht gleich in deiner Funktion wieder?

Quote:
Eine Globale Variabel wäre zwar ne Lösung, finde ich aber unschön. wie

Globale Variablen sind keine Lösung.

Quote:
kann ich aus einer anderen Funktion mit delete [] den Speicher von x
wieder freigeben?

Nein. Du hast den Speicher mit new belegt, dann musst du ihn auch mit delete
wieder freigeben. Wenn du mit new[] belegst, muss er auch wieder mit
delete[] freigegeben werden.
<scherz>Schreib dir doch den Pointer auf das Objekt in der Funktion in eine
Datei auf deine Platte und lade das ganze in deinem anderen Objekt wieder in
den RAM.</scherz>

Quote:
Ich könnte zwar den Prototypen ändern und die
Adresse mit übergeben, will aber nicht die Funktionen großartig
ändern.

Du hast ein massives Designproblem - ohne Veränderungen kannst du das nicht
lösen. Du solltest dir über deine gesamte Konzeption nochmals Gedanken
machen. Benutze das erzeugte Objekt als Rückgabewert, übergib Parameter als
Referenzen, nutze statische Attribute in einer Klasse... Das ist zu
schwammig, als dass man hier einen wirklich konkreten Designvorschlag machen
könnte.

Btw.: im Usenet sind volle Realnames üblich.

MfG,
Steffen Rauh

--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de

Back to top
Marcel Müller
Guest





PostPosted: Tue Sep 14, 2004 5:54 pm    Post subject: Re: Speicher frei geben Reply with quote

Shuo wrote:

Quote:
Ich habe mehrere Funktionen, in denen mit new Speicher belegt wird.
Die Variabel, die hinter der Speicherbelegung steht, ist keine
globale. Rückgabewert ist ein int und Übergabe sind zwei Objekte.
Der Prototyp (mit teilcode) sieht also folgendermaßen aus:
int bla function(object a, object b)
{
....
Klasse x = new x();
.....

return 3;

}

Dad Codefragment ergibt wenig Sinn, da die Variable x weder ein Pointer
ist, noch nach irgendwo außerhalb der Funktion zurückgegeben wird.

Quote:
Jetzt hab ich folgendes Problem. Ich muss diesen Speicher aus einer
anderen Klasse wieder frei geben.

Eine Globale Variabel wäre zwar ne Lösung, finde ich aber unschön. wie
kann ich aus einer anderen Funktion mit delete [] den Speicher von x
wieder freigeben? Ich könnte zwar den Prototypen ändern und die
Adresse mit übergeben, will aber nicht die Funktionen großartig
ändern.

Ohne Erklärung wie die Abhängigkeiten von x aussehen, ist eine Antwort
Raterei.


Stichworte zum Selbersuchen: object owner, boost::shared_ptr


Marcel

--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de

Back to top
Boris Glawe
Guest





PostPosted: Tue Sep 14, 2004 6:08 pm    Post subject: Re: Speicher frei geben Reply with quote

Quote:
int bla function(object a, object b)
{
....
Klasse x = new x();
.....

return 3;

}
Jetzt hab ich folgendes Problem. Ich muss diesen Speicher aus einer
anderen Klasse wieder frei geben.


Noch was: du musst in deinem Fall nicht mit dem new Operator arbeiten. Du kannst
dir das Objekt auch einfach auf den Stack legen, was folgendermaßen aussieht:


int bla function(object a, object b)
{
.....
Klasse x;
......

return 3;

}

Dadurch kreiert der compiler für die Funktion einfach einen Stack, der nicht nur
den Pointer zu deinem Objekt aufnimmt, sondern gleich das ganze Objekt selbst.
Dadurch wird das Objekt auch automatisch wieder vom Stack gelöscht, sobald die
Funktion abgearbeitet ist.

Dazu vielleicht etwas Hintergrundwissen zu Stack und Heaps:


Rufst du eine Funktion auf, dann werden die Anweisungen und Daten auf eine
Stapel (=Stack) gelegt. Der Prozessor arbeitet alle Anweisungen von oben nach
unten ob. Der Stack ist im Computer einfach ein Stück Arbeitsspeicher. Der
Compiler reserviert also genau so viel Arbeitsspeicher, dass alle Anweisungen
(die, wie alles andere auch, in Bits kodiert sind) und die Variablen genau
reinpassen. Schreibst du Anweisungen wie

int x = 0;

in deine Methode, dann muss der Compiler also Speicher für die Variable x und
für die Addieranweisung reservieren, die der Prozessor dann abarbeiten kann.

Das Gegenstück zum Stack ist der Heap. Heap heißt so viel, wie "Haufen". Es ist
eine Art unsortierter Speicherbereich. Du kannst Werte auf dem Heap speichern,
indem du new oder malloc() aurufst. new und malloc() erzeugen dein Objekt und
legen es auf den Heap. Da du aber nicht weißt, an welche Stelle im
Arbeitsspeicher das Objekt jetzt liegt, geben dir sowohl new als auch malloc()
einen Pointer auf diesen Speicher zurück.


void method(){

//]...}

Klasse *x = new Klasse()


//[...]

}


Dieses Beispiel macht folgendes:

Der Compiler weiß, wie groß ein Pointer auf den Typ " Klasse" ist und reserviert
auf dem Stack Platz für den Pointer. Dieser Pointer liefert dir aber nicht das
Objekt, sondern nur die adresse im Arbeitsspeicher. Der new Operator ereugt das
Objekt und legt es auf den heap. Die zurückgegeben Adresse sagt dir, wo der
Speicher ist.

Wenn du die Methode jetzt verlässt wird alles das gelöscht, was auf den Stack
liegt. Auf dem Stack liegt aber nur der Pointer und nicht das Objekt selbst.
Dieser Pointer ist damit verloren und damt auch die Information wo dein Objekt
auf dem Heap liegt. Das Resultat ist eine Meldung bei heise.de weil dein
Programm einen Memoryleak hat, also Speicher, der unbrauchbar deinen Rechner
vollmüllt.

Du kannst jetzt den Pointer allerdings als Rückgabewert der methode zurückgeben,
womit man das Objekt auch nach Abarbeitung der Methode noch benutzen kann (was
gerade einer der Vorteile von dynamischer Speicherreservieren ist).
Wird das Objekt aber nicht außerhalb der Klasse gebraucht was bei dir
offensichtlich der Fall ist, dann muss du es entweder selbst noch vor
Methodenende wieder mit delete freigeben oder - was noch geschickter ist - das
Objekt selbst auf den Stack legen. Im Grunde wird jedes Objekt, egal ob int,
char, MeineKlasse usw. auf den Stack gelegt, wenn du Anweisungen der folgenden
Art schreibst:

int x;
char c;
MeineKlasse klasse;

Auf dem heap landen die objekte nur wenn man new oder malloc() bebutzt (new
benutzt man unter C++, malloc() unter C).
Noch etwas: Sollten die Konstruktoren von MeinKlasse parameter erwwarten, also
z.B. so aussehen:

class MeineKlasse {

private:

double value;

public:

MeinKlasse(int x) {
value = x * 3.1415;
}


};


dann schreibt man einfach

MeinKlasse klasse(5);

um das Objekt "klasse" auf den Stack zu legen.

Dann sollte man aber auf gar keinen Fall den Fehler machen und irgendwie einen
Pointer auf diese Objekt außerhalb der Methode bereitstellen, weil es nach
Abarbeiten der Methode nicht mehr existiert. Ein Zugriff nach der Abarbeitung
würde sofort mit einer Speicherschutzverletzung bestraft werden.

Grüße Boris

--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de

Back to top
Shuo
Guest





PostPosted: Wed Sep 15, 2004 1:00 am    Post subject: Re: Speicher frei geben Reply with quote

Hallo nochmal!

Vielen Dank für die zahlreichen Antworten! Danke auch Dir Boris!

Ersteinmal...Sorry, ist natürlich ein Schreibfehler gewesen. sollte:
Klasse *x = new x(); heißen.
Auch der Prototyp sieht nicht wirklich so aus. Es werden natürlich
Referenzen übergeben.
Ok. Ich hab wohl mein Problem wirklich nicht gründlich genug beschrieben.
Jetzt werd ich wohl weiter ausholen müssen.
Ich werd das jetzt mal versuchen mit Worten zu beschreiben.
Ich habe eine Manager Klasse,..ein Singleton. Eine Andere Unit Klasse kann
mehrfach instanziiert werden. Diese Unit Klasse besitzt als Attribut ein
Objekt einer anderen Klasse. Der Interface Klasse.

So, folgendes passiert:
Es wird ein Objekt von der Manager Klasse instanziiert. Diese Klasse
besitzt eine Funktion, die AddUnit heißt. Diese Funktion hat als
Übergabeparameter eine IpAdresse. Hier wird jetzt mit dem New Operator ein
Unit Objekt angelegt, das wiederrum auch ein Interface Objekt mit der Ip
Adresse anlegt (auch mit New). Fragt jetzt nicht, warum zweimal, es ist so
weil die Interface Klasse die Netzwerkfunktionalität aufbaut und die Unit
Klasse andere Funktionen besitzt.
So, jetzt werden diese ganze Informationen über den Zeiger in einre map<>
abgelegt. Diese Funktion (AddUnit) liefert jetzt ein Handle zurück, dass
Informationen über die map-Verwaltung. Quasie den Platz.

So, jetzt mit diesen Zeigern aus der liste fein gearbeitet...Funktioniert
auch fein. Nun will ich zum Schluß alles wieder frei geben. Also quasie
alles was ich vorhin mit New reserviert habe, frei geben.

Ich weiß jetzt nicht, ob ich einen Denkfehler hab, oder ob ich den Wald
vor lauter Bäumen nicht mehr sehe.

Wäre super, wenn ihr mir Tipps geben könntet..

Schöne Grüße

Yang


Ps: Da im Usenet volle Realnames üblich sind: Mein Name ist Shuo! Zum
Vornamen Yang!

--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
Back to top
Markus Breuer
Guest





PostPosted: Wed Sep 15, 2004 7:54 am    Post subject: Re: Speicher frei geben Reply with quote

Quote:
So, jetzt mit diesen Zeigern aus der liste fein
gearbeitet...Funktioniert auch fein. Nun will ich zum Schluß alles
wieder frei geben. Also quasie alles was ich vorhin mit New reserviert
habe, frei geben.

Ich weiß jetzt nicht, ob ich einen Denkfehler hab, oder ob ich den Wald
vor lauter Bäumen nicht mehr sehe.

Wäre super, wenn ihr mir Tipps geben könntet..

Wenn du den Zeiger doch in der Liste stehen hast, dann müsstest du den
Speicher doch freigeben, sobald du den Listeneintrag entfernst.
Deine erste Funktion allokiert demnach den Speicher, parkt den Zeiger in
der map und gibt den map-key als Handle zurück.
Nun benötigst du eine weitere Funktion, der du den map-key übergibst und
die diesen Eintrag aus der map wieder entfernt. Beim entfernen wird
mittels delete einfach der Speicher wieder freigegeben.

Habe ich da etwas übersehen?

Gruß Markus

--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de

Back to top
Steffen Rauh
Guest





PostPosted: Wed Sep 15, 2004 7:57 am    Post subject: Re: Speicher frei geben Reply with quote

Quote:
Ich habe eine Manager Klasse,..ein Singleton. Eine Andere Unit Klasse kann
mehrfach instanziiert werden. Diese Unit Klasse besitzt als Attribut ein
Objekt einer anderen Klasse. Der Interface Klasse.

Also grafisch sieht das dann so aus:
Manager (Singleton) -> Unit -> Interface

Quote:
So, folgendes passiert:
Es wird ein Objekt von der Manager Klasse instanziiert. Diese Klasse
besitzt eine Funktion, die AddUnit heißt. Diese Funktion hat als
Übergabeparameter eine IpAdresse. Hier wird jetzt mit dem New Operator ein
Unit Objekt angelegt, das wiederrum auch ein Interface Objekt mit der Ip
Adresse anlegt (auch mit New). Fragt jetzt nicht, warum zweimal, es ist so
weil die Interface Klasse die Netzwerkfunktionalität aufbaut und die Unit
Klasse andere Funktionen besitzt.
So, jetzt werden diese ganze Informationen über den Zeiger in einre map
abgelegt. Diese Funktion (AddUnit) liefert jetzt ein Handle zurück, dass
Informationen über die map-Verwaltung. Quasie den Platz.

Was sind "diese ganzen Informationen"? Legst du die Units in einer Map im
Manager ab? Was ist dann der Wert? Wird das Handle als Schlüssel verwendet
und die Units als Wert? Warum als Handle eine Information zu Position in der
Map zurückgeben und nicht den Pointer auf das eigentliche Objekt?
Sicherheitsbedenken?

Quote:
So, jetzt mit diesen Zeigern aus der liste fein gearbeitet...Funktioniert
auch fein. Nun will ich zum Schluß alles wieder frei geben. Also quasie
alles was ich vorhin mit New reserviert habe, frei geben.

Ok, das ganze sieht ja jetzt schon etwas anderst aus (brauchbarer Wink.
Trotzdem frage ich mich, wieso dein Speicher überläuft, wenn du sowieso alle
Objekte bis zum Schluß halten musst? Zu wenig RAM? Räumt dein OS hinter dir
nicht auf? Nun gut, zum eigentlichen Problem:
Lasse im Destruktor zu deinem Manager durch alle Units iterieren und
zerstöre sie mit delete. Im Destruktor von Unit zerstöre das
Interface-Objekt. Falls du dich jetzt fragst, wie du dein Singleton
zerstören kannst: implementiere eine weitere statische Funktion wie
CSingleton::Instance(), die du für den Zugriff verwendest und lasse dort das
Objekt zerstören CSingleton::Destroy(). Diese Funktion rufst du dann kurz
vor Programmende auf.

MfG,
Steffen Rauh

--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de

Back to top
Shuo
Guest





PostPosted: Wed Sep 15, 2004 8:37 am    Post subject: Re: Speicher frei geben Reply with quote

Am Wed, 15 Sep 2004 09:57:47 +0200 schrieb Steffen Rauh
<steffen.rauh (AT) gmx (DOT) de>:

Quote:
Ich habe eine Manager Klasse,..ein Singleton. Eine Andere Unit Klasse
kann
mehrfach instanziiert werden. Diese Unit Klasse besitzt als Attribut ein
Objekt einer anderen Klasse. Der Interface Klasse.

Also grafisch sieht das dann so aus:
Manager (Singleton) -> Unit -> Interface

So, folgendes passiert:
Es wird ein Objekt von der Manager Klasse instanziiert. Diese Klasse
besitzt eine Funktion, die AddUnit heißt. Diese Funktion hat als
Übergabeparameter eine IpAdresse. Hier wird jetzt mit dem New Operator
ein
Unit Objekt angelegt, das wiederrum auch ein Interface Objekt mit der Ip
Adresse anlegt (auch mit New). Fragt jetzt nicht, warum zweimal, es ist
so
weil die Interface Klasse die Netzwerkfunktionalität aufbaut und die
Unit
Klasse andere Funktionen besitzt.
So, jetzt werden diese ganze Informationen über den Zeiger in einre
map
abgelegt. Diese Funktion (AddUnit) liefert jetzt ein Handle zurück, dass
Informationen über die map-Verwaltung. Quasie den Platz.

Was sind "diese ganzen Informationen"? Legst du die Units in einer Map im
Manager ab? Was ist dann der Wert? Wird das Handle als Schlüssel
verwendet
und die Units als Wert? Warum als Handle eine Information zu Position in
der
Map zurückgeben und nicht den Pointer auf das eigentliche Objekt?
Sicherheitsbedenken?

Ich sehr schon, ich muß mich klarer Ausdrücken. Der Zeiger, des Objektes
indem Infos stecken wird in der Map abgelegt.
Genau. So mache ich es. Das Handle ist der Schlüssel, die Unit der
dazugehöriger Wert.
Ich muss aus Sicherheitsgründen ein Handle zurück geben und kann nicht den
Zeiger zurück geben..


Quote:

So, jetzt mit diesen Zeigern aus der liste fein
gearbeitet...Funktioniert
auch fein. Nun will ich zum Schluß alles wieder frei geben. Also quasie
alles was ich vorhin mit New reserviert habe, frei geben.

Ok, das ganze sieht ja jetzt schon etwas anderst aus (brauchbarer Wink.
Trotzdem frage ich mich, wieso dein Speicher überläuft, wenn du sowieso
alle
Objekte bis zum Schluß halten musst? Zu wenig RAM? Räumt dein OS hinter
dir
nicht auf?

Ich darf leider nicht viel Speicher verwenden...

Quote:
Nun gut, zum eigentlichen Problem:
Lasse im Destruktor zu deinem Manager durch alle Units iterieren und
zerstöre sie mit delete. Im Destruktor von Unit zerstöre das
Interface-Objekt. Falls du dich jetzt fragst, wie du dein Singleton
zerstören kannst: implementiere eine weitere statische Funktion wie
CSingleton::Instance(), die du für den Zugriff verwendest und lasse dort
das
Objekt zerstören CSingleton::Destroy(). Diese Funktion rufst du dann kurz
vor Programmende auf.

MfG,
Steffen Rauh



Im Destruktor vom Manager iteriere ich auch durch die ganze map und rufe
für jede unit den Destruktor auf.
Das Interface Objekt wird auch mit delete dann auch im Destruktor von Unit
gelöscht.
Der mit New angelegte Speicher aus einer Funktion von der Unit Klasse wird
doch durch den Aufruf vom Destruktor nicht gelöscht, oder? Der muß doch
expliziet mit delete aufgerufen werden, oder?
Was das zerstören von dem Singleton angeht. Ich bin hingeganen und hab
einfach einen Pointer vom Typ Manager angelegt und in einem Block mit New
Speicher allokiert. Am Ende, wenn ich aus dem Block wieder raus komme,
rufe ich einfach ein delete auf....
--
Erstellt mit M2, Operas revolutionärem E-Mail-Modul:
http://www.opera.com/m2/

--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de

Back to top
Steffen Rauh
Guest





PostPosted: Wed Sep 15, 2004 9:17 am    Post subject: Re: Speicher frei geben Reply with quote

Quote:
Im Destruktor vom Manager iteriere ich auch durch die ganze map und rufe
für jede unit den Destruktor auf.

Du rufst den Destruktor auf? Aber kein Delete? Du musst delete aufrufen,
damit der Speicher freigegeben wird - da wird dan automatisch der Destruktor
aufgerufen.

Quote:
Das Interface Objekt wird auch mit delete dann auch im Destruktor von Unit
gelöscht.
Der mit New angelegte Speicher aus einer Funktion von der Unit Klasse wird
doch durch den Aufruf vom Destruktor nicht gelöscht, oder? Der muß doch
expliziet mit delete aufgerufen werden, oder?

Ja genau. Irgendwie kommen wir der Sache nicht näher, oder? Also dann mal
etwas konkreteren Code, wie ich das ganze verstehe:

class CInterface
{
// ...
};

class CUnit
{
private:
CInterface* _Interface;

public:
CUnit()
{
_Interface = new CInterface();
}
~CUnit()
{
delete _Interface;
}
};

class CManager
{
public:
typedef unsigned int THandle;

private:
std::map<THandle, CUnit*> _UnitList;

public:
~CManager()
{
for (/* iterate through all unit list entries */)
{
delete (MyIterator->second);
}
_UnitList.clear();
}
THandle AddUnit(std::string IpAddress)
{
// calculate handle
THandle NewHandle = // ...

// create unit
CUnit* NewUnit = new CUnit();

// add to unit list
_UnitList[NewHandle] = NewUnit;
return NewHandle;
}
void RemoveUnit(THandle Handle)
{
// make sure handle exists
// ...

// destroy unit
delete _UnitList[Handle];

// remove entry from unit list
// ...
}
};

Wo liegt jetzt also genau das Problem bzw. das Speicherleck?

Quote:
Was das zerstören von dem Singleton angeht. Ich bin hingeganen und hab
einfach einen Pointer vom Typ Manager angelegt und in einem Block mit New
Speicher allokiert. Am Ende, wenn ich aus dem Block wieder raus komme,
rufe ich einfach ein delete auf....

Ist dann aber kein wirkliches Singleton, weil du ja mehrere Objekte von
Manager anlegen könntest, wenn du es wolltest. Ein Singleton stellt sicher,
dass egal was der Programmierer auch macht, es maximal ein Objekt dieser
Klasse gibt.

MfG,
Steffen Rauh

--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de

Back to top
Shuo
Guest





PostPosted: Wed Sep 15, 2004 10:51 am    Post subject: Re: Speicher frei geben Reply with quote

Am Wed, 15 Sep 2004 11:17:24 +0200 schrieb Steffen Rauh
<steffen.rauh (AT) gmx (DOT) de>:

Quote:
Im Destruktor vom Manager iteriere ich auch durch die ganze map und rufe
für jede unit den Destruktor auf.

Du rufst den Destruktor auf? Aber kein Delete? Du musst delete aufrufen,
damit der Speicher freigegeben wird - da wird dan automatisch der
Destruktor
aufgerufen.

Das Interface Objekt wird auch mit delete dann auch im Destruktor von
Unit
gelöscht.
Der mit New angelegte Speicher aus einer Funktion von der Unit Klasse
wird
doch durch den Aufruf vom Destruktor nicht gelöscht, oder? Der muß doch
expliziet mit delete aufgerufen werden, oder?

Ja genau. Irgendwie kommen wir der Sache nicht näher, oder? Also dann mal
etwas konkreteren Code, wie ich das ganze verstehe:

class CInterface
{
// ...
};

class CUnit
{
private:
CInterface* _Interface;

public:
CUnit()
{
_Interface = new CInterface();
}
~CUnit()
{
delete _Interface;
}
};

class CManager
{
public:
typedef unsigned int THandle;

private:
std::map<THandle, CUnit*> _UnitList;

public:
~CManager()
{
for (/* iterate through all unit list entries */)
{
delete (MyIterator->second);
}
_UnitList.clear();
}
THandle AddUnit(std::string IpAddress)
{
// calculate handle
THandle NewHandle = // ...

// create unit
CUnit* NewUnit = new CUnit();

// add to unit list
_UnitList[NewHandle] = NewUnit;
return NewHandle;
}
void RemoveUnit(THandle Handle)
{
// make sure handle exists
// ...

// destroy unit
delete _UnitList[Handle];

// remove entry from unit list
// ...
}
};

du hast das total richtig verstanden.das problem liegt, das der angelegte
spreicherbereich (new Cunit und new Cinterface) immernoch nicht
freigegeben ist. das einzigste was ich anders mache ist, dass ich nicht
delete (MyIterator->second) im destruktor aufrufe sondern gleich den
destruktor ~Cunit. aberdas dürfte doch nichts ändern?

Quote:

Wo liegt jetzt also genau das Problem bzw. das Speicherleck?

Was das zerstören von dem Singleton angeht. Ich bin hingeganen und hab
einfach einen Pointer vom Typ Manager angelegt und in einem Block mit
New
Speicher allokiert. Am Ende, wenn ich aus dem Block wieder raus komme,
rufe ich einfach ein delete auf....

Ist dann aber kein wirkliches Singleton, weil du ja mehrere Objekte von
Manager anlegen könntest, wenn du es wolltest. Ein Singleton stellt
sicher,
dass egal was der Programmierer auch macht, es maximal ein Objekt dieser
Klasse gibt.

MfG,
Steffen Rauh


Und wie kann ich es sicherstellen, dass genau ein objekt davon
instanziiert wird?!

nochmals danke für deine hilfe! schön zu wissen, dass mich einer
versteht:-)

yang

--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de

Back to top
Steffen Rauh
Guest





PostPosted: Wed Sep 15, 2004 11:50 am    Post subject: Re: Speicher frei geben Reply with quote

Quote:
du hast das total richtig verstanden.das problem liegt, das der angelegte
spreicherbereich (new Cunit und new Cinterface) immernoch nicht
freigegeben ist.

Doch. In meinem Source ist zu jedem new auch ein delete vorhanden. Ich hab'
ja alle Pointer so abgelegt, dass ich sie zu einem späteren Zeitpunkt
wiederfinden kann. Spätestens wenn ein übergeordnetes Objekt zerstört wird,
werden auch die Unterobjekte explizit mit delete freigegeben.

Quote:
das einzigste was ich anders mache ist, dass ich nicht
delete (MyIterator->second) im destruktor aufrufe sondern gleich den
destruktor ~Cunit. aberdas dürfte doch nichts ändern?

Doch. delete ruft den Destruktor auf und gibt den Speicher frei. Wenn du nur
den Destruktor aufrufst, zerstörst du zwar das Objekt, der Speicherbereich
bleibt aber allokiert. In 99,99% aller Fälle wirst du niemals den Destruktor
direkt aufrufen müssen. Das ist nur in extremen Ausnahmefällen notwendig, wo
man dann auch ganz genau wissen muss, weshalb man das macht.

Quote:
Und wie kann ich es sicherstellen, dass genau ein objekt davon
instanziiert wird?!

Am besten nach "singleton design pattern" googlen oder gleich "Design
Patterns; Elements of Reusable Object-Oriented Software" von Gamma, Helm,
Johnson und Vlissides kaufen.

MfG,
Steffen Rauh

--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de

Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ (German) All times are GMT
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.