speicherleak in hashtabelle mit separate chaining



  • Falsches Forum: korrekt wäre C++
    Bitte mal verschieben.
    Simon



  • Dieser Thread wurde von Moderator/in Jochen Kalmbach aus dem Forum C++/CLI mit .NET in das Forum C++ verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • Sry, aber das liest sich doch keiner durch...

    ~Bucket () {
               Bucket *freeme;
    
            while (next) {
                 freeme = next; 
                 next = next->next;
                  delete freeme;
            }
          }
    

    normalerweise geht so was mit kleinen fkt viel hübscher + übersichtlicher - idR braucht man auch ein clear in der klasse und ruft das einfach auf...
    das clear an sich ist wieder so aufgebaut:
    while (! empty()) pop_back();
    etc
    das hat nicht nur den vorteil, dass man quellcode nicht 20mal schreiben muss, sondern auch, dass man ihn besser testen kann - und vor allem, schneller seine aufgabe ablesen kann...

    for (size_t i = 0; i < len; i++){
    
            if ( !member(e[i]) ){
    
                size_t pos = hash( e[i] );
    
                Bucket<E>* neuBuck = new Bucket<E>();
                neuBuck->key = e[i];
                neuBuck->next = array[pos];
                array[pos] = neuBuck;
                n++;
    

    Konstruktoren sind dir offensichtlich nicht all zu geläufig?!

    wenn du das ein wenig übersichtlicher gestaltest und dann noch ein wenig mehr (vll nciht gleich alles ^^) postest, wird dir sicher jmd helfen!

    bb



  • Bucket() : next(NULL){}
        ~Bucket () {
     		  Bucket *freeme;
    
    	    while (next) {
    		     freeme = next; 
    		     next = next->next;
     		     delete freeme;
      	  }
      	}
     };
    

    Geht das nicht voll in die Hose?
    Der Destruktor für das erste Bucket-Objekt (b1) wird aufgerufen. Dieser setzt freeme auf den eigenen Member "b1->next", danach weist er dem eigenen Member "b1->next" den Wert von "b1->next->next" zu, danach wird freeme == b1->Next per delete über den Jordan geschickt.

    Dummerweise geht "delete freeme" jetzt auch auf die eigenen childElemente los. Und welcher ist gleich der erste? korrekt. Genau der der jetzt in b1->next gespeichert ist. Dieser wird als erstes gelöscht.

    Da bei "delete b1" der Zeiger "b1->next" nicht NULL ist, aber schon durch "delete freeme" gelöscht ist, gibt es nen Crash.
    Da solltest du dich mal bissl mit Rekursion beschäftigen, und ob du das auch wirklich willst.



  • unskilled schrieb:

    Konstruktoren sind dir offensichtlich nicht all zu geläufig?!

    wenn du das ein wenig übersichtlicher gestaltest und dann noch ein wenig mehr (vll nciht gleich alles ^^) postest, wird dir sicher jmd helfen!

    bb

    also konstruktoren sind mir wohl geläufig. sonst würde das programm garnicht funktionieren. wollte nicht alles posten.

    das problem ist, höchstwahrscheinlich im destructor. wie gesagt, es bleibt belegter speicher übrig.

    wie ist es denn mit den destructoren? diese werden doch nach programmende automatisch aufgerufen oder nicht?

    edit:
    würdest du dich etwas auskennen, wüsstest du, dass das noch lang nicht "alles" ist. sind schon so an die 350 zeilen. aber was solls, du wolltest mir eh nicht helfen, weil das thema hast du nicht angeschnitten, sondern mir was ganz anderes erzählt.



  • Lecker schrieb:

    Bucket() : next(NULL){}
        ~Bucket () {
     		  Bucket *freeme;
    
    	    while (next) {
    		     freeme = next; 
    		     next = next->next;
     		     delete freeme;
      	  }
      	}
     };
    

    Geht das nicht voll in die Hose?
    Der Destruktor für das erste Bucket-Objekt (b1) wird aufgerufen. Dieser setzt freeme auf den eigenen Member "b1->next", danach weist er dem eigenen Member "b1->next" den Wert von "b1->next->next" zu, danach wird freeme == b1->Next per delete über den Jordan geschickt.

    Dummerweise geht "delete freeme" jetzt auch auf die eigenen childElemente los. Und welcher ist gleich der erste? korrekt. Genau der der jetzt in b1->next gespeichert ist. Dieser wird als erstes gelöscht.

    Da bei "delete b1" der Zeiger "b1->next" nicht NULL ist, aber schon durch "delete freeme" gelöscht ist, gibt es nen Crash.
    Da solltest du dich mal bissl mit Rekursion beschäftigen, und ob du das auch wirklich willst.

    den teil kann man vergessen .. vorallem wenn der part auch im ~ContSepChain auch nochmal auftaucht, gibts segmentation fault.

    ich würde den ~Bucket einfach leer lassen und ~ContSepChain alle arbeit machen lassen. müsste eigentlich funktionieren oder?



  • Bucket::~Bucket
    {
        delete next;
        next = NULL;
    }
    

    Reicht vollkommen.



  • Lecker schrieb:

    Bucket::~Bucket
    {
        delete next;
        next = NULL;
    }
    

    Reicht vollkommen.

    dem stimm ich zu, der code vom ~Bucket davor war noch vom experimentieren. verzeihung.

    ontopic:
    ich habe ein testprogramm um meine hashtabelle zu testen. wenn ich das testprogramm einfach mit "quit" beende, merke ich (wenn ich debugge mit std::cout in z.b. ~bucket) dass der destructor nicht aufgerufen wird.. kann das sein?



  • notnerdyet schrieb:

    würdest du dich etwas auskennen, wüsstest du, dass das noch lang nicht "alles" ist.

    Wo hat er das denn behauptet?

    aber was solls, du wolltest mir eh nicht helfen, weil das thema hast du nicht angeschnitten, sondern mir was ganz anderes erzählt.

    Er hilft dir doch. Also Leute gibts 😕

    wenn ich das testprogramm einfach mit "quit" beende

    Wasn das?



  • sorry. er hat geschrieben, ich soll ned alles posten, hab ich ja ned. 😉



  • Michael E. schrieb:

    wenn ich das testprogramm einfach mit "quit" beende

    Wasn das?

    das ist ein programm mit dem ich die methoden usw. ausprobieren kann.



  • notnerdyet schrieb:

    sondern mir was ganz anderes erzählt.

    Genau - ich hab dir gesagt, was du machen musst, um selbst den Fehler zu finden...
    Du sollst deine Funktionen kleiner und übersichtlicher gestalten - wenn du meinen weg genommen hättest, hättest du schon bei pop_front() gesehen, was passiert - und wärst überrascht gewesen - aber hättest es iwann verstanden und gemerkt, was du falsch machst...

    bb

    edit:
    zu konstruktoren:

    Bucket<E>* neuBuck = new Bucket<E>(); 
                neuBuck->key = e[i]; 
                neuBuck->next = array[pos]; 
                array[pos] = neuBuck;
    

    dort sieht man doch, dass da was nicht hinhaut...

    array[pos] = new Bucket<E>(e[i], array[pos]);
    müsstest Bucket eben nur nen passenden Konstruktor verpassen - und schon könnte man mit einem Block erfassen, was dort vor sich geht...

    bb



  • sorry fürs missverständnis.

    auf deiner seite ist auch ein missverständnis passiert. ich habe meinen konstruktor noch garnicht gepostet. das was du da zitierst ist meine add-methode.

    mein konstruktor sieht so aus:

    template <typename E>
     ContSepChain<E>::ContSepChain( ) : tablesize( 7 ), n( 0 ) { 
    
    	array = new Bucket<E>* [tablesize];	
    	if (array != NULL){
    		for (size_t i = 0; i < tablesize; i++)
    				array[i] = NULL; 
    	}			
     }
    


  • @unskilled: danke für deine mühe mein programm zu vereinfachen.

    das problem liegt aber wie gesagt im speicherleak. das programm funktioniert ja. vereinfachungen es besser lesen zu können, hilft mir dabei auch nicht weiter.

    irgndwelche ideen wie ich den destruktor gestalten kann bzw. sonstwas tun soll um meine speicherleaks zu entfernen?



  • notnerdyet schrieb:

    das problem liegt aber wie gesagt im speicherleak. das programm funktioniert ja. vereinfachungen es besser lesen zu können, hilft mir dabei auch nicht weiter.

    Das ist wie: "Ich hab nen Problem, weiß nicht, wieso genau, aber besser verstehen brauch ich hier gar nichts - ich warte einfach, bis mir jmd mein Problem löst - und das nächste Mal mach ichs wieder genau so" -.-



  • mag sein, dass ich den eindruck vermittle, da ich extrem unter zeitdruck stehe, das problem lösen zu müssen. verstehen jedoch will ichs schon.



  • unskilled schrieb:

    zu konstruktoren:

    Bucket<E>* neuBuck = new Bucket<E>(); 
                neuBuck->key = e[i]; 
                neuBuck->next = array[pos]; 
                array[pos] = neuBuck;
    

    dort sieht man doch, dass da was nicht hinhaut...

    array[pos] = new Bucket<E>(e[i], array[pos]);
    müsstest Bucket eben nur nen passenden Konstruktor verpassen - und schon könnte man mit einem Block erfassen, was dort vor sich geht...

    bb

    hab nen konstruktor für bucket erstellt, läuft jetzt auch mit der zeile: array[pos] = new Bucket<E>(e[i], array[pos]);

    jedoch kann ich den speicher den ich mit "new" erstellt habe immer noch nicht löschen. für hilfreiche hinweise bin ich sehr dankbar!!!



  • habs nun selbst gelöst.

    tipps von "unskilled" waren wie der name ja scho sagt .... 😉



  • notnerdyet schrieb:

    tipps von "unskilled" waren wie der name ja scho sagt .... 😉

    Jedenfalls weiß ich, wie ich meine Klassen implementiere, um so was selbst (vorzeitig) zu finden - und die Lösung war ja schon auf der ersten Seite, also brauchte ich auch nichts mehr zum Problem an sich sagen - nur meine Aussage erklären - von wegen Konstruktoren sind dir kein Begriff...

    bb


Anmelden zum Antworten