Rückgabewert mit new angelegt, wo loeschen?
-
Ich möchte etwas aus einem Stringtable lesen und dies zurückgeben.
Hab mir das folgendermaßen vorgestellt:char* loadFromTable(unsigned int ID) { HRSCR scrHandle; DWORD sizeByte; srcHandle = FindResource(GetModuleHandle(NULL), MAKEINTRESOURCE(ID), RT_STRING ); if( scrHandle != NULL ) { sizeByte = SizeofResource( NULL, rsrc ); if( sizeByte > 0 ) { sizeChar = sizeByte/sizeof(char) +1; strTextBuffer = new char[sizeChar]; LoadString(GetModuleHandle(NULL) ,ID strTextBuffer,sizeChar); return strTextBuffer; } } return -1; }die Variable strTextBuffer liegt doch nun im Heap, oder?
Wird bei erneuten Aufruf der Funktion die Variable überschrieben, oder neuer Speicher reserviert?
Wenn neuer speicher reserviert wird, wie und wo delete ich den denn dann?
gehe ich hier vernünftig vor oder macht man sowas in der Regel anders?muli
-
jepp das ist ein Problem, bzw. Designfrage... wie es bspw. in Jave mit dem Garbage Collector gelöst wurde..
Du müsstest sog. Smart Pointer Benutzen... dies Pointer sind intelligent, und löschen ihre Instanz sobal sie nicht mehr genutzt werden... ansonsten ist es schwer zu sagen wo du die Instanz löschen musst...es könnte ja sein das du diese Funktion nicht immer aufruftst,
1. Entwerder nutzt Smart-Pointer
2. Überdenke deine Programm Desing
3. Oder:
//Zeiger deklarieren, initalisiren char *p=NULL; //Funktion mit zeiger referenz void Funktion(char *&p){ p= new char..... } // löschen wenn zeiger auf eine Instanz zeigt! if(p) delete p;P.S: rufst du mehreremale die Funktion auf, wierd immer wieder neuer Speicherreserveire, und die Adresse in p gespeichert, wobei die Addresse der Alten speicehrreservierung gelöscht wird.... nicht gut!
-
BorisDieKlinge schrieb:
// löschen wenn zeiger auf eine Instanz zeigt! if(p) delete p;Das 'if' ist hier überflüssig.
Wieso eigentlich ne Zeiger-Referenzübergabe? Wenn man schon s 'nen Zeiger nimmt, kann man ihn auch per 'return' zurückgeben. Besser wird's dadurch natürlich auch nicht …
-
ja gut ist eigenlich egal ,aber wenn:
void Funktion(char *&p){ if(p) delete p; p= new char.... }dann ist das Problem weg, das die refernez überschrieben wird, wenn die funktione mehrermalle aufgerufen wird!!
P.S. if überflüssig? wird das überprüft beim delete obs NULL ist??
-
BorisDieKlinge schrieb:
P.S. if überflüssig? wird das überprüft beim delete obs NULL ist??
Ja.
-
ist das schon immer so? vor jahren musste man das noch glaub ich...
-
Seit der Standard garantiert das operator delete() selbst prüft ob der übergebene Zeiger 0 ist und new/[] ohnehin keinen nullzeiger zurückliefert ist das prüfen auf einen null-zeiger überflüssig. Mag sein, dass das früher anders geregelt war.
-
Bevor es nicht standardisiert war, war es eben verschieden. Aber wen verwundert das?
-
muli schrieb:
...
die Variable strTextBuffer liegt doch nun im Heap, oder?
...Jepp
muli schrieb:
...
Wird bei erneuten Aufruf der Funktion die Variable überschrieben, oder neuer Speicher reserviert?
...Beides. strTextBuffer bekommt eine neue Adresse und zeigt auf neu reservierten Speicher der Größe sizeChar.
Wenn vorher Speicher reserviert und nicht freigegeben wurde und wenn die Adresse nicht woanders zwischengespeichert wurde, dann ist dieser Speicher im Heap nicht mehr erreichbar.
muli schrieb:
...
Wenn neuer speicher reserviert wird, wie und wo delete ich den denn dann?
gehe ich hier vernünftig vor oder macht man sowas in der Regel anders?
...
muliIm prinzip ist es egal, wo du den Speicher frei gibst.
Arrays werden mit delete [] freigegeben. Ansonsten gibst du nur ein einziges Element frei, der Rest ist dann nicht mehr zugänglich ( verwitwetes Objekt )p.
-
ich seh in der funktion nirgendwo eine deklaration von strTextBuffer. also ich geh ich mal davon aus, dass diese global geschehen ist.
dadurch lässt sich das "problem" womöglich sehr leicht lösen:
delete strTextBuffer; strTextBuffer = new char[sizeChar];die funktion selbst kümmert sich darum, dass der speicher freigegeben wird, bevor dem pointer neuer speicher zugewiesen wird.
das ist natürlich nur dann eine lösung, wenn zwischenzeitlich nicht an irgendeiner anderen stelle ein anderer pointer auf genau diese adresse gebogen wurde. denn dann würde dieser logischerweise irgendwann ins leere greifen und dein programm fliegt dir um die ohren.
sollte das der fall sein und das design es nicht zulassen, das ganze anders zu lösen, dann ist nen smart_ptr wahrscheinlich die einfachste lösung.
-
delete[] strTextBuffer;Als Smartpointer wäre hier wohl boost::shared_array<char> das richtige. auto_ptr geht ja nicht.
-
< Error Detected >
void Funktion(char *&p)< Correction >
void Funktion(char *p)< Error Detected >
delete strTextBuffer< Correction >
delete [] strTextBuffer< Rules >
new -> delete new [] -> delete []
-
< Memoryleak detected >
Code Corrector [active] schrieb:
< Error Detected >
void Funktion(char *&p)< Correction >
void Funktion(char *p)
-
Da kann man mal wieder sehen, wie objektorientiertes Programmieren mit steigender Komplexität vermeintlich das Denken ersetzt.
Wir schreiben einfach delete und Peng alles ist gut.
Oder hach, nehmen wir doch gleich Smartpointer, dann brauchen wir gar nicht mehr zu denken.Muahuahua.
Where is my head today ?
MfG
I forgot my nameOh, God, make my sourcecode, amen.
-
-> "Wir schreiben einfach delete und Peng alles ist gut. "
oder wir nehmem Java...Aber ich will was zum denken... alles selber in der Hand haben
-
Brainless Wanderers schrieb:
Da kann man mal wieder sehen, wie objektorientiertes Programmieren mit steigender Komplexität vermeintlich das Denken ersetzt.
Wir schreiben einfach delete und Peng alles ist gut....Ha ! Da zeigt sich jahrelange Erfahrung mit großen Projekten !!

"Wir": Schreibe einmal new/malloc und x-mal "delete/free" (und bei jeder Änderung wieder ein paar mehr)
OO: Schreibe EINMAL "smartpointer" - fertig für alle Zeit!Kann jeder selbst wählen, was komfortabler, sicherer, schöner, kürzer, übersichtlicher, .... findet.

Gruß,
Simon2.
-
Simon2 schrieb:
OO: Schreibe EINMAL "smartpointer" - fertig für alle Zeit!
Nein: Nicht OO, sondern RAII. Der Unterschied: das Laufzeitoverhead.

(OO impliziert für mich Laufzeitpolymorphie.)
-
Konrad Rudolph schrieb:
Simon2 schrieb:
OO: Schreibe EINMAL "smartpointer" - fertig für alle Zeit!
Nein: Nicht OO, sondern RAII. Der Unterschied: das Laufzeitoverhead.

(OO impliziert für mich Laufzeitpolymorphie.)
Nur zur Erinnerung: ICH war nicht derjenigem der die Verwendung von smartpointern auf "OO" verkürzte.

Gruß,
Simon2.
-
We would have to point out:
Smart Pointers are smashing, they kick ass.

-
Konrad Rudolph schrieb:
Wieso eigentlich ne Zeiger-Referenzübergabe? Wenn man schon s 'nen Zeiger nimmt, kann man ihn auch per 'return' zurückgeben. Besser wird's dadurch natürlich auch nicht …
soll das heißen wenn man pointer returnt das das schlechter stil ist? ich finde es eig. nen gutes hilfsmittel um platz auf dem heap zusparen. was macht es für nen sinn nen riesiges objekt zu returnen? mann kann auch einfach nen pointer darauf returnen.