Toon posts:

[C++] geheugen vrijgeven *

Pagina: 1
Acties:

Verwijderd

Topicstarter
Ok, een behoorlijke noob vraag van mij.

In C++ kun je gealloceerde data die je hebt aangemaakt met 'new' deleten met de functie 'delete'. Delete gooit dan de pointer weg.

Heeft dit hetzelfde effect als 'pointer = NULL'?

In code:

C++:
1
2
myType * blaat = new myType;
delete blaat;


Is dat equivalent met:
C++:
1
2
myType * blaat = new myType;
blaat = NULL;


Deze vraag komt voort uit mijn huidige programmeerbezigheid. Ik heb een grote structuur opgebouwd in het geheugen en die wil ik weer weggooien. Maar volgens mij maakt de compiler geen verschil tussen 'delete' en 'delete []', waardoor ik soms de pointers van een hele array weggooi terwijl ik nog niet klaar ben met die array. Die dingen NULL maken schijnt te werken, maar nu wil ik dus even weten of het ook echt hetzelfde effect heeft --> geheugen vrij maken.

  • xoror
  • Registratie: November 1999
  • Niet online
pointer = null; maken krijg je memleaks (als je nog geen delete etc gedaan heb).

je maakt immers de pointer alleen null. het geheugen is nog niet vrij gegeven, de referentie erheen ben je nu alleen kwijt.

verder zit er wel een fundamenteel verschil tussen delete en delete [].
de tweede is om array te deleten de eerste niet.

[ Voor 18% gewijzigd door xoror op 26-03-2003 02:52 ]

Mitsubishi Warmtepomp Uitlezen / Besturen | Optimaliseren


Verwijderd

Topicstarter
Was ik al bang voor.

Maar volgens mij neemt mijn compiler (g++) het niet zo nauw met het verschil tussen 'delete' en 'delete []'. Wanneer ik namelijk een array delete en het eerste element met 'delete' weggooi, dan bestaat het tweede element ook niet meer.

Het rare is dat het niet voor ieder geval zo is.

Klinkt vaag en ik kan hier wel mijn hele code gaan posten, maar daar wordt je ook niet veel wijzer van vrees ik.

  • xoror
  • Registratie: November 1999
  • Niet online
eh mijn g++ doet delete en delete [] heel correct hoor :)
ik denk dat je gewoon foutje gemaakt heb

Mitsubishi Warmtepomp Uitlezen / Besturen | Optimaliseren


Verwijderd

Topicstarter
Ok, dan post ik hier toch maar mijn code, want ik begrijp er echt geen *** meer van.

De geheugenstructuur die ik opbouw is een boom en hangt aan elkaar door middel van de volgende structs:

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
typedef struct BoundingBox {
  union {
    int x1;
    int x;
  };
  union {
    int y1;
    int y;
  };
  union {
    int x2;
    int lap;
  };
  union {
    int y2;
    int dataBlock;
  };
  double beginTime;
  double endTime;
} boundingBoxType;

typedef struct Branch {
  boundingBoxType * boundingBox;
  void * child;
} branchType;

const int BRANCHING_FACTOR = 64;

typedef struct Node {
  int count;
  int level;
  branchType * branch[BRANCHING_FACTOR];
} nodeType;


Wat hebben we nu? We hebben een boom die een hele verzameling nodes bevat. Iedere node heeft diverse kinderen en helemaal onderaan in de boom hangen de bladeren die punten in een 3D ruimte voorstellen. De parents van die bladeren vormen bounding-boxes in de node erboven en parents daarvan weer bounding-boxes in de node daarboven, enz. BRANCHING_FACTOR is het maximaal aantal elementen in 1 node, level is het level waar de node zich bevindt (0 == bladeren onderin de boom), count is het aantal elementen (bladeren of bounding boxes) in een node. Deze structuur staat vast, dus aub geen commentaar in deze thread over de efficientie etc. :)

Ik bouw nu een hele boom op met behulp van deze structuur, gaat allemaal prima, ik kan ook mooi de gegevens uitlezen uit de boom, geen probleem allemaal, maar nu wil ik hem dus deleten met de volgende code (bij aanroepen van de functie wordt de root-node meegegeven):

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
void deleteNode (nodeType * node) {
  if (node->level != 0) {
    for (int i=0; i<node->count; i++)
        deleteNode((nodeType *)node->branch[i]->child);
  }
  for (int i=0; i<node->count; i++) {
    delete(node->branch[i]->boundingBox);
    delete(node->branch[i]);
  }
  delete(node);

  return;
}


Wanneer nu de eerste keer delete(node) is aangeroepen, krijg ik een segmentation fault voor de volgende node die aan de beurt is. Haal ik hem weg, dan krijg ik een segmentation fault wanneer de eerste serie nodes op level 0 is gedaan en als de eerste branch[i] op level 1 is verwijderd.

Degene die mijn probleem begrijpt en me kan helpen is een held _/-\o_

/edit
O ja, reden van de unions in boundingBoxType is dat ik lui ben en een boundingBox op deze manier ook gewoon als leaf kan functioneren, met normale benamingen voor de elementen :*)

/edit 2
Code van deleten compacter en overzichtelijker gemaakt. Werkt nog steeds niet.

[ Voor 13% gewijzigd door Verwijderd op 26-03-2003 04:04 ]


  • xoror
  • Registratie: November 1999
  • Niet online
je delete je 'uiteinden' dubbel. (na je recursie aanroep delete je 1e keer, en de 2e
keer in de else aanroep als je in de recursie call zit en een uiteinde heb gevonden).

het moet dus zo worden denk ik:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
void deleteNode (nodeType * node){ 
  if (node->level != 0) { 
    for (int i=0; i<node->count; i++)
        deleteNode((nodeType *)node->branch[i]->child); 
    }

  for (int i=0; i<node->count; i++) { 
    delete(node->branch[i]->boundingBox); 
    delete(node->branch[i]); 
  } 

  delete(node); 
  return; 
}


je kan memleaks in het vervolg op een systematische manier opsporen met tools he ? valgrind is er bijv een ervan.

[edit]
hmm mijn code en jouw code doen precies het zelfde. verder zie ik niet zo gauw een twee drie een fout erin. Die van mij is alleen wat simpeler. Mijn vermoeden blijft staan dat je geheugen dubbel delete. Aanwijzing daarvoor is dat de = null versie wel werkt.

[ Voor 21% gewijzigd door xoror op 26-03-2003 04:02 ]

Mitsubishi Warmtepomp Uitlezen / Besturen | Optimaliseren


Verwijderd

Topicstarter
Dit is helaas alleen een manier van beter opschrijven. Wat in de 'else' staat gebeurt in de 'if' ook en kan dus net zo goed uit de 'if' verdwijnen en dan zonder 'else' erbuiten gezet worden. Is precies hetzelfde, maar dan anders (en overzichtelijker, dank hiervoor :P) opgeschreven.

En werkt dus ook niet, helaas.

Bedankt voor de tip trouwens, valgrind ken ik niet. Kun je misschien een paar alternatieven noemen? Ik heb hier geen rechten om software te installen, ken je misschien een standaard tooltje voor het opsporen van memory leaks dat bij redhat meegeleverd wordt?

/edit
En verder staat er bij mij ook nog een overbodige 'if' in de eerste for-lus, die kan er ook uit 8)7

[ Voor 13% gewijzigd door Verwijderd op 26-03-2003 04:01 ]


  • xoror
  • Registratie: November 1999
  • Niet online
wat je kan doen is, alles wat je gedelete heb op null zetten. (dus na dat je gedelete heb). Voordat je delete moet je controleren of de pointer niet op null staat. zo voorkom je dubbel deletes. Verder kan je wat cout of printfs gebruiken om te kijken wat je delete etc.

kijk op http://freshmeat.net/browse/836/?topic_id=836 voor meer dev/profiling etc tools

Mitsubishi Warmtepomp Uitlezen / Besturen | Optimaliseren


Verwijderd

Topicstarter
xoror schreef op 26 maart 2003 @ 03:51:
hmm mijn code en jouw code doen precies het zelfde. verder zie ik niet zo gauw een twee drie een fout erin. Die van mij is alleen wat simpeler. Mijn vermoeden blijft staan dat je geheugen dubbel delete. Aanwijzing daarvoor is dat de = null versie wel werkt.
Dat denk ik ook, blijkbaar is datgene dat ik delete op dat moment al gedelete. Maar het vage is dat ik dat volgens mij helemaal niet doe.

Nog iets vreemds trouwens (jaja, het wordt steeds vager):

Ik bouw die boom op uitgaande van een grote verzameling gegevens, dat gaat perfect. Na opbouwen schrijf ik de hele boom naar een file, ook prima. Dan wil ik dus die boom deleten uit het geheugen, dat gaat dus niet, dan gaat mijn deleteNode functie de fout in. Maar ik kan wel ieder element uit de boom op het scherm afdrukken, ze bestaan dus allemaal wel!

Wanneer ik dezelfde boom niet genereer, maar gewoon uit de file weer inlees, dan werkt de deleteNode functie wel goed op die boom in het geheugen :?

Is dat niet vreemd?

Verwijderd

Topicstarter
xoror schreef op 26 maart 2003 @ 04:09:
wat je kan doen is, alles wat je gedelete heb op null zetten. (dus na dat je gedelete heb). Voordat je delete moet je controleren of de pointer niet op null staat. zo voorkom je dubbel deletes. Verder kan je wat cout of printfs gebruiken om te kijken wat je delete etc.

kijk op http://freshmeat.net/browse/836/?topic_id=836 voor meer dev/profiling etc tools
Tnx!

/me gaat op null pointers checken en website bezoeken

  • xoror
  • Registratie: November 1999
  • Niet online
Verwijderd schreef op 26 March 2003 @ 04:09:
[...]


Dat denk ik ook, blijkbaar is datgene dat ik delete op dat moment al gedelete. Maar het vage is dat ik dat volgens mij helemaal niet doe.

Nog iets vreemds trouwens (jaja, het wordt steeds vager):

Ik bouw die boom op uitgaande van een grote verzameling gegevens, dat gaat perfect. Na opbouwen schrijf ik de hele boom naar een file, ook prima. Dan wil ik dus die boom deleten uit het geheugen, dat gaat dus niet, dan gaat mijn deleteNode functie de fout in. Maar ik kan wel ieder element uit de boom op het scherm afdrukken, ze bestaan dus allemaal wel!

Wanneer ik dezelfde boom niet genereer, maar gewoon uit de file weer inlees, dan werkt de deleteNode functie wel goed op die boom in het geheugen :?

Is dat niet vreemd?
dan is een van je funkties fout lijk me ;)

Mitsubishi Warmtepomp Uitlezen / Besturen | Optimaliseren


Verwijderd

Topicstarter
xoror schreef op 26 maart 2003 @ 04:15:
[...]


dan is een van je funkties fout lijk me ;)
Maar dat lijkt me ook weer heel vreemd. Stappen die ik doe:

- genereer boom1 in geheugen met als root root1
- schrijf boom1 weg naar file
- lees boom1 uit file als boom2 met root root2
- delete boom2 uit geheugen met deleteNode(root2)
- delete boom1 uit geheugen met deleteNode(root1)

Deleten van boom2 gaat prima, deleten van boom1 gaat fout.

Bomen zijn exact hetzelfde.

:|

  • xoror
  • Registratie: November 1999
  • Niet online
wat gebeurt er als je deleteNode(root2); comment, gaat deleteNode(root1) wel goed dan ?

anyway wat je nog kan doen is assert() gebruiken. bijv voor elke delete assert(ptr != null);
als de ptr nulll is dan stopt het programma en zegt waar dat optreedt.

Mitsubishi Warmtepomp Uitlezen / Besturen | Optimaliseren


Verwijderd

Topicstarter
De volgorde van de functies maakt niet uit. Ik gebruik deze volgorde gewoon omdat anders het programma al gestopt is voordat boom2 gedelete is.

Ik heb nog even heel precies gechecked en de bomen en structuren zijn exact hetzelfde. Ik druk ze vanuit het geheugen af met dezelfde functie en krijg precies hetzelfde resultaat --> structuur en gegevens kloppen dus.

Ik ga nog even proberen met assert en null pointer checks enzo.

Enorm bedankt voor de hulp! (en dat op dit tijdstip :D)

  • xoror
  • Registratie: November 1999
  • Niet online
dan lijk me echt dat een van je funkties niet correct zijn. als hij een core dumped kan je dat call trace opvragen he ? kan je zien waar ie ongeveer doodgaat. anyway, als je het echt niet aan de praat krijg kan je altijd een container gebruiken. voor jouw tree is deze denk ik erg geschikt : http://www.damtp.cam.ac.uk/user/kp229/tree/

Mitsubishi Warmtepomp Uitlezen / Besturen | Optimaliseren


Verwijderd

Topicstarter
Aaaaaarrrgghh.....

Nu heb ik dus checks op null-pointers toegevoegd:

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void deleteNode (nodeType * node) {
  if (node->level != 0) {
    for (int i=0; i<node->count; i++)
        deleteNode((nodeType *)node->branch[i]->child);
  }
  for (int i=0; i<node->count; i++) {
    if (node->branch[i]->boundingBox != NULL)
      delete(node->branch[i]->boundingBox);
    if (node->branch[i] != NULL)
      delete(node->branch[i]);
  }
  if (node != NULL)
    delete(node);

  return;
}


Maar nog steeds dezelfde segmentation faults. Het wordt dus niet veroorzaakt door een pointer die nergens meer naar wijst, want NULL zijn ze niet.

Begin nu een beetje gek te worden hier 8)7

Verwijderd

Topicstarter
xoror schreef op 26 March 2003 @ 04:53:
dan lijk me echt dat een van je funkties niet correct zijn. als hij een core dumped kan je dat call trace opvragen he ? kan je zien waar ie ongeveer doodgaat. anyway, als je het echt niet aan de praat krijg kan je altijd een container gebruiken. voor jouw tree is deze denk ik erg geschikt : http://www.damtp.cam.ac.uk/user/kp229/tree/
Hmmm, een core wordt niet gedumped, dus die kan ik niet bekijken (toch?).

  • xoror
  • Registratie: November 1999
  • Niet online
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
void deleteNode (nodeType * node) { 
  if (node->level != 0) { 
    for (int i=0; i<node->count; i++) 
        if (node->branch[i]->child != null)
            deleteNode((nodeType *)node->branch[i]->child);
  } 
  for (int i=0; i<node->count; i++) { 
    if (node->branch[i]->boundingBox != NULL) {
      delete(node->branch[i]->boundingBox);
      node->branch[i]->boundingBox = NULL;
    } 
    if (node->branch[i] != NULL) {
      delete(node->branch[i]);
      node->branch[i] = NULL;
     } 
  } 
  if (node != NULL) { 
    delete(node);
    node = NULL; 
  }
  return; 
}


zo moet ie.

maar ik denk niet dat je probleem in de delete funktie zit. ik vermoed eerder in een van die andere funkties.

ik ga zo maar ff :z :z :z
haal je prog anders door gdb, of frontend ervan ddd. anders moet je z'n stl-alike container usen. voordeel is dat die voor elke structuur werkt en goed getest is.

[ Voor 17% gewijzigd door xoror op 26-03-2003 05:17 ]

Mitsubishi Warmtepomp Uitlezen / Besturen | Optimaliseren


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 21-08 17:14
Verwijderd schreef op 26 March 2003 @ 04:55:
Aaaaaarrrgghh.....

Nu heb ik dus checks op null-pointers toegevoegd:

C++:
1
2
  if (node != NULL)
    delete(node);


Maar nog steeds dezelfde segmentation faults. Het wordt dus niet veroorzaakt door een pointer die nergens meer naar wijst, want NULL zijn ze niet.
Ja, dat werkt dus niet zo. Exact diezelfde test zit al in delete ( en zat ook al in free() in C ). Wat er bedoeld is is
code:
1
2
delete node;
node = NULL; // zodat je niet opnieuw delete op dezelfde waarde aanroept

Evengoed is delete vaak een teken van matig design, en hier ook. De nette oplossing is hier boost::shared_ptr< Type >. Dat is een slimme pointer; daar kun je wel NULL aan assignen en dan gaat het 'Type' object dus wel keurig weg. Maar ook als je dat niet doet, wordt het 'Type' object opgeruimd zodra de shared_ptr< > weg gaat. Dat betekent dat je alleen de root van de tree weg hoeft te gooien; de rest volgt vanzelf.

[ Voor 6% gewijzigd door MSalters op 26-03-2003 09:59 ]

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • ProgrammerX
  • Registratie: Juli 2002
  • Laatst online: 26-02-2021
MSalters schreef op 26 March 2003 @ 09:57:

Evengoed is delete vaak een teken van matig design, en hier ook. De nette oplossing is hier boost::shared_ptr< Type >. Dat is een slimme pointer; daar kun je wel NULL aan assignen en dan gaat het 'Type' object dus wel keurig weg. Maar ook als je dat niet doet, wordt het 'Type' object opgeruimd zodra de shared_ptr< > weg gaat. Dat betekent dat je alleen de root van de tree weg hoeft te gooien; de rest volgt vanzelf.
Doet die slimme pointer dan niet precies hetzelfde als de implementatie met delete enz. ? Alleen zorgt die slimme pointer in dat geval zelf voor de delete. Dan vind ik niet echt dat je kan spreken van een 'matig' design.

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 22-08 01:56
Is het nu echt zo moelijk om een zinnige topic title te kiezen? Verder vraag ik me af of je ooit een debugger gebruikt hebt?

In C++ gebruiken we trouwens geen 'NULL' maar '0' voor null-waarden en daar hoef je niet op te checken, want een null-pointer mag je gewoon deleten (al gebeurt er dan niets).

De kans is groot dat je probleem te maken heeft met een stuk geheugen dat je meerdere malen vrijgeeft (meerdere keren delete op dezelfde pointer) of dat je vrijgegeven geheugen benadert (eerste delete op een pointer, en deze daarna dereferencen).Zoals xoror aangeeft kun je dat voorkomen door vrijgegeven pointerwaarden op 0 te zetten (al 'weet' je niet altijd waar die allemaal staan) maar dat is een beetje compenseren voor een slecht in elkaar stekend ontwerp; schijnbaar weet je niet precies waar welk geheugen vrijgegeven wordt.

De makkelijkste manier om uit te zoeken wat het geval is, is door een debugger aan te raken. Gebruik van allerlei smart pointers lijkt me overkill voor een simpele boomstructuur en geeft je bovendien absoluut geen inzicht in de aard van het probleem, wat me in jouw situatie veel belangrijker lijkt. Ik ben sowieso geen voorstander van mensen die met smart pointers werken, maar geen idee hebben hoe het alloceren en vrijgeven van geheugen moet. Dat gaat gegarandeerd fout (zeker met auto_ptr's, hoe dat met die boost dingen zit weet ik niet).

Tenslotte: de kans dat je een fout in GCC (of een andere gangbare C/C++ compiler) vindt is ontzettend klein; als je zelf al aangeeft dat je weinig programmeerervaring hebt, kun je beter de bescheidenheid proberen op te brengen om de fout in ieder geval bij jezelf te zoeken, dan bij een goede compiler.

[ Voor 3% gewijzigd door Soultaker op 26-03-2003 12:49 ]


  • WildernessChild
  • Registratie: Februari 2002
  • Niet online

WildernessChild

Voor al uw hersenspinsels

Even weer helemaal terug naar het begin: pak een goed C++ boek en zoek daarin op: het woord DESTRUCTOR. Het is namelijk een stuk netter om de boom z'n eigen troep op te laten ruimen dan om van buitenaf met je vingers erin te gaan roeren.

Maker van Taekwindow; verplaats en resize je vensters met de Alt-toets!


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 21-08 17:14
ProgrammerX schreef op 26 March 2003 @ 12:35:
[...]
Doet die slimme pointer dan niet precies hetzelfde als de implementatie met delete enz. ? Alleen zorgt die slimme pointer in dat geval zelf voor de delete. Dan vind ik niet echt dat je kan spreken van een 'matig' design.
Nee; twee keer 0 assignen aan die smart pointer gaat goed, twee keer een pointer deleten gaat fout.
Bovendien, als je de assignment "vergeet" dan gebeurt de delete automatisch.
Kortom: of je nou 0,1, of vaker probeert het object op te ruimen, het wordt precies 1 keer opgeruimd - zoals het hoort.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


Verwijderd

Topicstarter
Is het nu echt zo moelijk om een zinnige topic title te kiezen? Verder vraag ik me af of je ooit een debugger gebruikt hebt?
Ik had inderdaad de moeite moeten nemen een andere topic titel te kiezen, mijn fout. Als een mod hem alsnog wil veranderen, graag. Problemen met vrijgeven van geheugen lijkt me wel ok. En ja, ik heb weleens een debugger gebruikt.
Tenslotte: de kans dat je een fout in GCC (of een andere gangbare C/C++ compiler) vindt is ontzettend klein; als je zelf al aangeeft dat je weinig programmeerervaring hebt, kun je beter de bescheidenheid proberen op te brengen om de fout in ieder geval bij jezelf te zoeken, dan bij een goede compiler.
Naar aanleiding van mijn probleem ben ik rond gaan zoeken op verschillende sites en las ik ergens dat sommige compilers niet altijd verschil maken tussen delete en delete []. Dat dus automatisch delete [] op een array uitgevoerd wordt wanneer je delete aanroept op het eerste element. Lijkt me een beetje sterk, maar is het niet logisch dat ik daar dan onder andere aan denk? Heeft niks met het opbrengen van bescheidenheid te maken.

En waar geef ik aan dat ik weinig programmeerervaring heb? Programmeerervaring heb ik genoeg, maar mijn kennis van C/C++ reikt nog niet zover dat ik al helemaal thuis ben in die taal. Ik ben de laatste die een fout meteen bij de compiler zoekt en niet in de eerste plaats bij zichzelf.

Knurft.

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 22-08 01:56
Verwijderd schreef op 26 March 2003 @ 23:21:
En ja, ik heb weleens een debugger gebruikt.
Gebruik 'm nu dan ook, alsjeblieft.
Naar aanleiding van mijn probleem ben ik rond gaan zoeken op verschillende sites en las ik ergens dat sommige compilers niet altijd verschil maken tussen delete en delete []. Dat dus automatisch delete [] op een array uitgevoerd wordt wanneer je delete aanroept op het eerste element. Lijkt me een beetje sterk, maar is het niet logisch dat ik daar dan onder andere aan denk? Heeft niks met het opbrengen van bescheidenheid te maken.
Bron?

Sowieso had je zelf kunnen bedenken dat zo'n fundamentele fout niet meer in een gangbare compiler voorkomt. Waarom vermeldt je in je opening post trouwens niet welke compiler je gebruikt, als je denkt dat het daar aan zou kunnen liggen?
En waar geef ik aan dat ik weinig programmeerervaring heb?
Nou ja, de topic title doet vermoeden dat je in ieder geval weinig C++ ervaring hebt. Een goede programmeur stelt intelligente vragen en geeft zinnige informatie; nu is jouw opening post niet ontzettend slecht (er komen veel slechter voorbij op GoT) maar het doet me toch niet echt aan iemand denken die wél veel programmeerervaring heeft.
Programmeerervaring heb ik genoeg, maar mijn kennis van C/C++ reikt nog niet zover dat ik al helemaal thuis ben in die taal. Ik ben de laatste die een fout meteen bij de compiler zoekt en niet in de eerste plaats bij zichzelf.
Waarom schrijf je dan: "Maar volgens mij maakt de compiler geen verschil tussen 'delete' en 'delete []', waardoor ik soms de pointers van een hele array weggooi terwijl ik nog niet klaar ben met die array."?
Knurft.
Oh, gaan we zo beginnen. Misschien moet je de FAQ maar eens gaan doornemen? Je hebt duidelijk een verkeerd beeld van de manier waarop we hier met elkaar omgaan.

Verwijderd

Topicstarter
Soultaker schreef op 26 March 2003 @ 23:36:
Oh, gaan we zo beginnen. Misschien moet je de FAQ maar eens gaan doornemen? Je hebt duidelijk een verkeerd beeld van de manier waarop we hier met elkaar omgaan.
Excuses, beetje chagrijnig vanochtend. Krijg je na een avond stappen, flink drinken en weer vroeg aan het werk.


Euhmmm, de bron ff denken. Heb het ergens op cplusplus.com gelezen volgens mij. Stond ergens iets over compilers die delete en delete[] 'without distinction' gebruiken.

Maar let's stick to the main problem, het lijkt me dat mijn deleteNode functie zou moeten werken? Met de debugger zie ik niets raars in het doorlopen van de functie, maar gaat hij wel blijkbaar iets proberen voor de tweede keer te deleten, ik kan er alleen niet achter komen hoe het de eerste keer dan precies is gebeurd :?

Verwijderd

Topicstarter
WildernessChild schreef op 26 March 2003 @ 15:42:
Even weer helemaal terug naar het begin: pak een goed C++ boek en zoek daarin op: het woord DESTRUCTOR. Het is namelijk een stuk netter om de boom z'n eigen troep op te laten ruimen dan om van buitenaf met je vingers erin te gaan roeren.
Ok, dat kan ik natuurlijk doen en is netter natuurlijk, maar dan verschuif ik het probleem naar de destructor toe. Het probleem blijft en is hetzelfde.

Of heb jij met die destructor andere ideeen?

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 22-08 01:56
Verwijderd schreef op 27 March 2003 @ 01:38:
Excuses, beetje chagrijnig vanochtend. Krijg je na een avond stappen, flink drinken en weer vroeg aan het werk.
Accoord; kan gebeuren.
Euhmmm, de bron ff denken. Heb het ergens op cplusplus.com gelezen volgens mij. Stond ergens iets over compilers die delete en delete[] 'without distinction' gebruiken.
Het maakt niet echt uit dat die compilers geen verschil maken (waardoor je ook delete op arrays of delete[] op objecten kunt gebruiken zonder fatale gevolgen); dit betekent alleen dat jouw fouten niet gedetecteerd worden. Goede code wordt dan nog steeds goed uitgevoerd.
Maar let's stick to the main problem, het lijkt me dat mijn deleteNode functie zou moeten werken? Met de debugger zie ik niets raars in het doorlopen van de functie, maar gaat hij wel blijkbaar iets proberen voor de tweede keer te deleten, ik kan er alleen niet achter komen hoe het de eerste keer dan precies is gebeurd :?
Het kan ook zo zijn dat je een pointer niet geinitialiseerd hebt (waardoor 'ie nergens naar verwijst). Dan kun je 'm ook niet vrijgeven. Werkt de suggestie van xoror (expliciet alle pointer waarden die je hebt gedelete op 0 zetten) wel?

In principe zou je ook een geheugendebugger kunnen gebruiken of zelf even delete overriden, zodat je kunt weergeven wat er zoal gealloceerd en vrijgegeven wordt. (Ik weet niet of dit ook static, dus beperkt tot één source file, mogelijk is; dat zou ideaal zijn).

Als je er daarmee allemaal niet uitkomt, kun je je code reduceren tot het absolute minimum waarbij de fout nog optreedt. Als je die code hier plaatst en hij is niet te lang, kan vast iemand de fout wel aanwijzen (of lokaal proberen te reproduceren).

We weten trouwens nog steeds niet welk platform en welke compiler je gebruikt (in verband met foutentolerantie en -signalering en eventuele bugs). Ik stel dus nogmaals voor dat je de QuickStart even doorleest; dit is gewoon nuttige informatie die je eigenlijk al direct in je starting post had moeten vermelden.

edit:
Nog zo iets wat ik al eerder vroeg: waar crashed 'ie nu precies? Je krijgt een segfault, zeg je, en daar hoort een backtrace bij. Laat die eens zien (of kijk er zelf eens naar). Je doet namelijk vrij veel dingen met delete([]) en zo blijft het maar gissen waar we de fout moeten zoeken.

[ Voor 8% gewijzigd door Soultaker op 27-03-2003 02:52 ]


Verwijderd

callstack's en watch-windows,
breakpoints,
safe delete macro's,
auto_ptr's en reference counting...

Het zijn allemaal je vriendjes !
Maak er gebruik van ! :)

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-08 13:19

.oisyn

Moderator Devschuur®

Demotivational Speaker

wat doet een safe delete macro?

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Primal
  • Registratie: Augustus 2001
  • Laatst online: 19:55
.oisyn schreef op 27 March 2003 @ 16:19:
wat doet een safe delete macro?
Bijvoorbeeld dit:

C++:
1
#define SAFE_DELETE(pPointer) {delete pPointer; pPointer = NULL;}


En dan gaat het vooral om het 2e statement. Ten eerste scheelt het iedere keer 1 regel code in je source ;) en ten tweede (het belangrijkste): bij consequent gebruik van een dergelijke macro vergeet je nooit een pointer te herinitialiseren op NULL na gebruik.

[ Voor 31% gewijzigd door Primal op 27-03-2003 18:47 ]

"The fastest code, is the code that is never called."


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 22-08 01:56
Primal schreef op 27 March 2003 @ 18:44:
Bijvoorbeeld dit:
C++:
1
#define SAFE_DELETE(pPointer) {delete pPointer; pPointer = NULL;}


En dan gaat het vooral om het 2e statement. Ten eerste scheelt het iedere keer 1 regel code in je source ;) en ten tweede (het belangrijkste): bij consequent gebruik van een dergelijke macro vergeet je nooit een pointer te herinitialiseren op NULL na gebruik.
Nogmaals, in C++ gebruik je geen NULL maar 0. Los daarvan zie ik niet in waarom je in een normale situatie je pointers op 0 wilt zetten nadat je hun waarden vrijgegeven hebt.

Garandeer je daarmee dat geheugen precies éénmaal wordt vrijgegeven? Nee, want er kunnen best meerdere pointers naar hetzelfde geheugen verwijzen (en je zet met je macro slechts één hiervan op 0). De garantie dat geheugen ueberhaupt vrijgegeven wordt is er ook niet.

Wat is precies dan precies het voordeel van jouw macro? Ik vermoedt dat het uitsluitend een uitnodiging is om maar op zoveel mogelijk plekken in de code delete statements toe te voegen, in de hoop dat al het geheugen vrijgegeven wordt. Door jouw handige macro hoef je niet meer na te denken over het eigendom (ownership) van het geheugen. Hierdoor wordt de kans dat je onverhoopt geheugen vergeet vrij te geven groter, aangezien je geen inzicht meer hebt in welk new-statement bij wel delete-statement hoort.

  • Rukapul
  • Registratie: Februari 2000
  • Laatst online: 23-08 14:24
Soultaker schreef op 27 March 2003 @ 20:55:
[...]

Nogmaals, in C++ gebruik je geen NULL maar 0. Los daarvan zie ik niet in waarom je in een normale situatie je pointers op 0 wilt zetten nadat je hun waarden vrijgegeven hebt.

Garandeer je daarmee dat geheugen precies éénmaal wordt vrijgegeven? Nee, want er kunnen best meerdere pointers naar hetzelfde geheugen verwijzen (en je zet met je macro slechts één hiervan op 0). De garantie dat geheugen ueberhaupt vrijgegeven wordt is er ook niet.

Wat is precies dan precies het voordeel van jouw macro? Ik vermoedt dat het uitsluitend een uitnodiging is om maar op zoveel mogelijk plekken in de code delete statements toe te voegen, in de hoop dat al het geheugen vrijgegeven wordt. Door jouw handige macro hoef je niet meer na te denken over het eigendom (ownership) van het geheugen. Hierdoor wordt de kans dat je onverhoopt geheugen vergeet vrij te geven groter, aangezien je geen inzicht meer hebt in welk new-statement bij wel delete-statement hoort.
In diverse boeken wordt deze methode aangeraden. Ik heb het even opgezocht in een E-book versie van C++ Unleashed:
Stray, Dangling, and Wild Pointers
If you delete a pointer that has already been deleted, you risk crashing your program. To ensure that this does not happen, make it a practice to set all deleted pointers to NULL. It is safe and legal to delete a null pointer, as shown in Listing 4.4.

[...]

Of course, this example is absurd because you would never delete the same pointer twice in a single method. The problem, of course, is that you often pass pointers into and out of methods, making copies as you go. In a complicated program, it is easy to lose track and accidentally delete an already deleted pointer. Making sure that you set deleted pointers to NULL (0) protects you from this error. It also ensures that if you try to use that pointer, you get an immediate crash rather than a subtle and difficult-to-find bug. If you are going to fail, you want to fail with a bang, not a whimper—that is, you want to fail predictably (so that you can find the bug) and you want to fail where the bug is, not later in the program.
Heb jij ook een bron dat het tegenovergestelde argumenteert en dus je mening onderbouwt?

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-08 13:19

.oisyn

Moderator Devschuur®

Demotivational Speaker

Soultaker schreef op 27 maart 2003 @ 20:55:
Nogmaals, in C++ gebruik je geen NULL maar 0. Los daarvan zie ik niet in waarom je in een normale situatie je pointers op 0 wilt zetten nadat je hun waarden vrijgegeven hebt.


in C wel dan? Daar is het ook simpelweg een define naar 0L
En als je een C++ header include dan wordt NULL op miraculeuze wijze ook gedefinieerd, dus het wordt niet bepaald afgedwongen om 0 te gebruiken. Bovendien is het gewoonweg niet fout.
Niettemin, ik vind het gebruik van NULL ipv 0 een stuk duidelijker. Geeft aan dat je met een pointer bezig bent, en niet met een integer. Dat de compiler het als hetzelfde ziet zal mij een worst wezen, als het voor de lezer maar duidelijk is wat ermee bedoeld wordt
Primal schreef op 27 maart 2003 @ 18:44:
Bijvoorbeeld dit:

C++:
1
#define SAFE_DELETE(pPointer) {delete pPointer; pPointer = NULL;}
ah, natuurlijk :) Ik zat even te denken aan een check op NULL oid, maar dat zou niet logisch zijn :)

Zijn overigens vrij nutteloos icm smartpointers ;)

.edit: overigens ben ik het wel met Soultaker eens. Je pointers op NULL zetten vind ik maar een halve oplossing, een hack om een paar probleempjes weg te moffelen. Punt is dat als je 2x dezelfde pointer delete dat meestal foute code is. Je wilt dus op 2 momenten een bepaalde pointer te deleten, en dus in feite 2x dat geheugen vrijgeven. Dat je 'm naar de eerste keer gelijk op NULL zet zorgt er alleen voor dat je programma op dat moment niet crasht. Maar voor hetzelfde geldt doe je voor die 2e delete ook nog even iets met die pointer. Dat dat 'toevallig' goed gaat wil nog niet zeggen dat dat betere code is.
Dan kun je nog beter je pointer zetten op een niet-geldig geheugenadres anders dan NULL (1 ofzo, of zoiets als 0xdeadbeef). Dan crasht je programma tenminste

[ Voor 26% gewijzigd door .oisyn op 28-03-2003 00:26 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • madwizard
  • Registratie: Juli 2002
  • Laatst online: 26-10-2024

madwizard

Missionary to the word of ska

.oisyn schreef op 28 March 2003 @ 00:14:
in C wel dan? Daar is het ook simpelweg een define naar 0L
En als je een C++ header include dan wordt NULL op miraculeuze wijze ook gedefinieerd, dus het wordt niet bepaald afgedwongen om 0 te gebruiken. Bovendien is het gewoonweg niet fout.
Niettemin, ik vind het gebruik van NULL ipv 0 een stuk duidelijker. Geeft aan dat je met een pointer bezig bent, en niet met een integer. Dat de compiler het als hetzelfde ziet zal mij een worst wezen, als het voor de lezer maar duidelijk is wat ermee bedoeld wordt
De includes voor windows programma's definieren NULL als volgt:
C++:
1
2
3
4
5
6
7
#ifndef NULL
#ifdef __cplusplus
#define NULL    0
#else
#define NULL    ((void *)0)
#endif
#endif


Verder ben ik het helemaal met .oisyn eens, NULL voor pointers en 0 voor niet pointers vind ik persoonlijk een stuk duidelijker. Denk dat het meer een kwestie van stijl dan van C++ sytax is.

www.madwizard.org


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-08 13:19

.oisyn

Moderator Devschuur®

Demotivational Speaker

madwizard schreef op 28 maart 2003 @ 00:22:
De includes voor windows programma's definieren NULL als volgt:


toch raar, een 0 assignen aan een pointer in C gaat prima

[ Voor 22% gewijzigd door .oisyn op 28-03-2003 00:28 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Eelis
  • Registratie: Januari 2003
  • Laatst online: 21-02-2015
.

[ Voor 99% gewijzigd door Eelis op 18-02-2015 19:44 ]


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 22-08 01:56
In C is een pointer gewoon een geheugenadres. NULL is een preprocessor definitie die een speciaal adres definieert dat als 'ongeldig' (ofzo) opgevat moet worden. In alle praktische situaties is NULL gewoon gelijk aan 0, zodat je gewoon "if(ptr)" en op 0 geinitialiseerd geheugen kunt gebruiken, maar dat is niet per definitie zo. NULL kan dus feitelijk een ander getal dan 0 zijn.

Dit levert gigantische problemen op met code die niet expliciet op gelijkheid aan NULL checkt (zoals: "if(ptr)") maar daarmee neemt de behoefte aan een vrije interpretatie van die waarde voor exotische platforms (waarvan ik eerlijk gezegd niet eens weet of ze bestaan) niet af.

In C++ heeft men dus besloten dat het token 0 in een pointer context overeenkomt met de null-pointer. Die wordt door de compiler dus omgezet. Tests op pointerwaarden worden ook omgeschreven, zodat er altijd een geldige controle plaatsvindt. Probleem opgelost, zonder nieuwe eisen te stellen aan de programmeur.

Waarom mag je dan geen NULL meer gebruiken? Het is een zeer onwaarschijnlijke situatie, maar het gaat om het principe: op een exotisch platform zou een C-library NULL kunnen definiëren als iets anders dan 0. De C++-compiler interpreteert die waarde dan ook niet meer als null-pointer en dan gaan allerlei dingen als het initialiseren van references (waarvan de compiler misschien wil controleren dat ze geldig zijn) fout.

Even concluderend: NULL gebruiken is dus prima in een omgeving die 'm definieert als 0 (of (void*)0, maar zeker niets anders) maar het levert in theorie problemen op wanneer er gebruik wordt gemaakt van C header files die misschien wel iets anders van plan zijn.

[ Voor 12% gewijzigd door Soultaker op 28-03-2003 04:44 ]


  • GrimaceODespair
  • Registratie: December 2002
  • Laatst online: 03:34

GrimaceODespair

eens een tettenman, altijd ...

Brian Stroustroup (maker van C++) haat macro's . Liever ziet hij templates. Die worden ook compiletime gersolved, maar zijn ook nog eens typesafe. Doch dit geheel terzijde ;)

Wij onderbreken deze thread voor reclame:
http://kalders.be


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 21-08 17:14
Soultaker schreef op 28 maart 2003 @ 04:42:
In C is een pointer gewoon een geheugenadres. NULL is een preprocessor definitie die een speciaal adres definieert dat als 'ongeldig' (ofzo) opgevat moet worden. In alle praktische situaties is NULL gewoon gelijk aan 0, zodat je gewoon "if(ptr)" en op 0 geinitialiseerd geheugen kunt gebruiken, maar dat is niet per definitie zo. NULL kan dus feitelijk een ander getal dan 0 zijn.

Dit levert gigantische problemen op met code die niet expliciet op gelijkheid aan NULL checkt (zoals: "if(ptr)") maar daarmee neemt de behoefte aan een vrije interpretatie van die waarde voor exotische platforms (waarvan ik eerlijk gezegd niet eens weet of ze bestaan) niet af.
De eerste twee regels kloppen nog wel, maar daarna ga je de fout in. Voor pointers geldt redelijk hetzelfde als voor floats: all-bits-zero != 0. Maar als je een NULL-pointer hebt, en die converteer je naar een int/_Bool dan krijg je altijd false. Dat geldt op elk platform, ook als NULL == (void*)0 bitpattern 0xffffffff zou hebben.
In C++ heeft men dus besloten dat het token 0 in een pointer context overeenkomt met de null-pointer. Die wordt door de compiler dus omgezet. Tests op pointerwaarden worden ook omgeschreven, zodat er altijd een geldige controle plaatsvindt. Probleem opgelost, zonder nieuwe eisen te stellen aan de programmeur.
Feitelijk correct, maar de reden is anders: (void*)0 kun in C++ je niet assignen aan een int*, er was behoefte aan een type-safe null-pointer-constant, en dat is het karakter '0' geworden (wat dus nogmaals niet overeen hoeft te komen met bitpattern 0x0000 )
Waarom mag je dan geen NULL meer gebruiken? Het is een zeer onwaarschijnlijke situatie, maar het gaat om het principe: op een exotisch platform zou een C-library NULL kunnen definiëren als iets anders dan 0. De C++-compiler interpreteert die waarde dan ook niet meer als null-pointer en dan gaan allerlei dingen als het initialiseren van references (waarvan de compiler misschien wil controleren dat ze geldig zijn) fout.
Weer fout, omdat NULL in C++ gedefinieerd is als 0 (soms 0UL oid, om onverwachte overloads betere warnings op te laten leveren).
Even concluderend: NULL gebruiken is dus prima in een omgeving die 'm definieert als 0 (of (void*)0, maar zeker niets anders) maar het levert in theorie problemen op wanneer er gebruik wordt gemaakt van C header files die misschien wel iets anders van plan zijn.
Nee, NULL is een macro uit je system headers, die zijn dus afhankelijk van het feit of je voor C of C++ compileert, en het type van NULL verschilt dus tussen C en C++. Voor beide geldt dat int* p = NULL; een null-pointer oplevert.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 22-08 01:56
Ok, ik zit er dus goed naast met betrekking tot het 0-verhaal. Ik zie nog steeds niet helemaal waarom een standaard C library NULL niet zou kunnen overriden in een C++ omgeving, maar goed; NULL schijnt ook goed te zijn. Echt mooi was een apart null keyword geweest (zoals in Java) omdat het token '0' nu een andere betekenis krijgt afhankelijk van de context waarin 'ie gebruikt wordt.

Maar goed; laat dat ons niet van het hoofdonderwerp afhouden.

[ Voor 4% gewijzigd door Soultaker op 28-03-2003 14:14 ]


  • Primal
  • Registratie: Augustus 2001
  • Laatst online: 19:55
Soultaker schreef op 27 maart 2003 @ 20:55:
[...]

Nogmaals, in C++ gebruik je geen NULL maar 0. Los daarvan zie ik niet in waarom je in een normale situatie je pointers op 0 wilt zetten nadat je hun waarden vrijgegeven hebt.......
Zo'n reactie had ik al wel verwacht, maar dat geeft verder niet. Ik gaf gewoon een direct antwoord op een directe vraag. Nothing more, nothing less....

Verder ben ik het met .oisyn eens: om een pointer te initialiseren voor gebruik, gebruik ik altijd NULL voor de duidelijkheid. Ik programmeer al lang C/C++. C++ heeft mooie eigenschappen, maar ik zal het nooit overdrijven in het gebruik. Je kunt er ook in verzanden zal ik maar zeggen (en dan heb ik het niet over of je initialiseert met '0' of met 'NULL').

Zo heb ik ooit op een project gewerkt, waarvan de projectleider perse wilde dat alles, maar dan ook alles OO zou gebeuren. Dat heeft ie geweten zal ik maar zachtjes uitgedrukt zeggen. Het project is 3 jaar geleden gestart en had na 1,5 a 2 jaar af moeten zijn. Dat is niet gelukt, ze zijn nu nog bezig .... Dan kun je zeggen: Ja, maar het ontwerp dan? Kunnen ze wel OO programmeren? Antwoord: Beide ja. Maar het werd compleet (lees dit schreeuwend :) ) overdreven. Ze waren zo diepgaand bezig met overloading, templates, nitty-gritty sh#t op de OO manier aan het schrijven (bij wijze van spreken, ontwierpen ze voor een 'int' nog een class met allerlei prut eromheen) etc. etc. het is gewoon allemaal te geworden. Ik zie OO dan ook als hulpmiddel en niet als doel (maar dat is mijn mening)
Wat is precies dan precies het voordeel van jouw macro?
Er zijn wel situaties te bedenken waarin het handig is om een dergelijke macro te gebruiken. En dan gaat het er niet om, om te voorkomen dat hetzelfde stuk geheugen meer dan 1 keer wordt vrijgegeven. Nee, je kunt bijv. ergens in een functie een test doen (je kan zelf best wel voorbeelden bedenken die hierop van toepassing zijn) op die pointer, voordat je hem gebruikt. Dan is het wel handig om te weten dat de pointer (!!!! -> want het gaat mij met deze macro om de pointer laten we wel duidelijk zijn, en niet om de andere 80 pointers die naar hetzelfde geheugengebied wijzen. Die heb ik voor het gemak buiten spel gezet) een valid waarde bevat of niet.
Ook tijdens het debuggen van code komt dit van pas als je een watch op een pointer hebt gezet. Ik vind het persoonlijk wel netjes als ik een pointer na de delete op NULL geïnitialiseerd zie worden, dan zie je in 1 oog opslag dat ie niet meer geldig is (en ook hier weer: je kunt zelf wel voorbeelden bedenken). Denk bij het bedenken van voorbeelden verder als het "Hello world" stadium a.u.b.

Maar nogmaals, iedereen heeft zijn eigen werkwijze en er zijn honderden manier om iets te doen. Ik wil ook niemand voor het hoofd stoten of zeggen: "kijk zo moet het", want dat kan en wil ik niet. Dat was alles wat ik hierover zeggen wil.

[ Voor 7% gewijzigd door Primal op 28-03-2003 16:09 ]

"The fastest code, is the code that is never called."


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 21-08 17:14
Primal schreef op 28 March 2003 @ 16:05:
Ik programmeer al lang C/C++. C++ heeft mooie eigenschappen, maar ik zal het nooit overdrijven in het gebruik. Je kunt er ook in verzanden zal ik maar zeggen

Zo heb ik ooit op een project gewerkt, waarvan de projectleider perse wilde dat alles, maar dan ook alles OO zou gebeuren. Dat heeft ie geweten zal ik maar zachtjes uitgedrukt zeggen. Het project is 3 jaar geleden gestart en had na 1,5 a 2 jaar af moeten zijn. Dat is niet gelukt, ze zijn nu nog bezig .... Dan kun je zeggen: Ja, maar het ontwerp dan? Kunnen ze wel OO programmeren? Antwoord: Beide ja. Maar het werd compleet (lees dit schreeuwend :) ) overdreven. Ze waren zo diepgaand bezig met overloading, templates, nitty-gritty sh#t op de OO manier aan het schrijven (bij wijze van spreken, ontwierpen ze voor een 'int' nog een class met allerlei prut eromheen) etc. etc. het is gewoon allemaal te geworden. Ik zie OO dan ook als hulpmiddel en niet als doel (maar dat is mijn mening)
OO is niet zaligmakend, daar heb je heel erg gelijk in. Kijk naar een boek als "Modern C++ Design", daar zie je dat "Generic Programming" heel vaak een alternatief voor Object-Oriented Programming is.
Dat wil overigens niet zeggen dat dat ook maar iets te maken heeft met waarom het genoemde project fout is gegaan. Het klinkt meer alsof ze veel te weinig hergebruikten.

Overigens hebben overloading en templates maar een beperkt verband met OO, kijk maar naar Java. OO kan zonder. Templates zijn gewoon een handige manier om een verzameling bijna identieke functies/klasses te maken (binnen zo'n project), en als je naar de STL kijkt zie je daar een library waarmee je zelf snel een linked list class kunt maken: std::list<Object>. Zelf doen kost veel meer dan 3 woorden.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • WildernessChild
  • Registratie: Februari 2002
  • Niet online

WildernessChild

Voor al uw hersenspinsels

Verwijderd schreef op 27 March 2003 @ 01:41:
[...]


Ok, dat kan ik natuurlijk doen en is netter natuurlijk, maar dan verschuif ik het probleem naar de destructor toe. Het probleem blijft en is hetzelfde.

Of heb jij met die destructor andere ideeen?
Je verschuift inderdaad het probleem, maar tegelijk maar je het jezelf een heel stuk eenvoudiger. In plaats van je delete-functie recursief te gebruiken, doe je in de destructor gewoon een delete op alle child nodes, en delete je nog de extra data die in een node wordt opgeslagen. Zo heb je dus een treenode die zijn eigen rommel opruimt, en dat is wel zo netjes en een heel stuk overzichtelijke en handiger.

Maker van Taekwindow; verplaats en resize je vensters met de Alt-toets!

Pagina: 1