Zeigerfrage



  • Folgendes Beispiel:

    BITMAP* tempanim =  new BITMAP[SIZE];
    for(int i = 0; i < SIZE;i++)// i = 0 to i = 28 
    {                      {
    tempanim[i] = *load_bitmap(temp.c_str(),NULL);
    }
    

    load_bitmap "Returns a pointer to the bitmap or NULL on error. Remember that you are responsible for destroying the bitmap when you are finished with it to avoid memory leaks. "

    load_bitmap lädt, wer hätte es gedacht ein bitmap. Nun würde ich gerne die Adresse dieser Bitmaps im Speicher in den Zeiger tempanim laden, ABER mir ist gerade was eingefallen:**

    Muss ich statt einen Zeiger auf einen Array, hier einen Array von Zeigern benutzen? Ich muss ja, da eine Adresse auf einen dynamischen Speicher zurückgegeben wird, diese Adresse beibehalten und nicht nur den Inhalt der Speicherzelle auf die die Adresse verweist.
    So wie es jetzt ist, speichere ich den Wert der Speicherzelle und verliere damit doch eine Adresse, oder? Ist diese Überlegung richtig?**

    Vielen Dank für eure Hilfe 🙂



  • *load_bitmap(temp.c_str(),NULL)
    

    Wenn das NULL zurück gibt bist du am Arsch. 🙂



  • ...und auch sonst hätte er ein Problem: Speicherlecks. loadbitmap erzeugt das Objekt im Heap (wahrscheinlich). Er kann es aber nicht mehr löschen, weil der Zeiger verloren geht.



  • sehr schön wie ihr auf meine Frage eingeht



  • kingcools2 schrieb:

    sehr schön wie ihr auf meine Frage eingeht

    Ich hatte es vorhin eilig und wollte nur kurz meinen Senf dazugeben. Ist denn jetzt noch was unklar?

    > Muss ich statt einen Zeiger auf einen Array, hier einen Array von Zeigern benutzen?

    Du musst gar nichts. Kommt drauf an, was Du willst. Du kannst die Zeiger auch in einem Vektor speichern, oder in einem shared_ptr kapseln. Es gibt sooooo viele Möglichkeiten.

    BITMAP** frickelig = new BITMAP*[SIZE];
    for (int k=0; k<SIZE; ++k) {
       frickelig[k] = loadbitmap(...);
    }
    for (int k=0; k<SIZE; ++k) {
       delete drickelig[k];
    }
    delete[] frickelig;
    
    vector<BITMAP*> besser (SIZE);
    for (int k=0; k<SIZE; ++k) {
       besser[k] = loadbitmap(...);
    }
    for (int k=0; k<SIZE; ++k) {
       delete besser[k];
    }
    
    vector<shared_ptr<BITMAP> > auchok (SIZE);
    for (int k=0; k<SIZE; ++k) {
       shared_ptr<BITMAP> sp ( loadbitmap(...) );
       auchok[k] = sp;
    }
    

    ...



  • krümelkacker schrieb:

    vector<shared_ptr<BITMAP> > auchok (SIZE);
    for (int k=0; k<SIZE; ++k) {
       shared_ptr<BITMAP> sp ( loadbitmap(...) );
       auchok[k] = sp;
    }
    

    ...

    Wenn der Compiler schon unique_ptr aus C++0x kennt, dann lieber vector<unique_ptr<BITMAP>> oder alternativ boost::ptr_vector.

    shared_ptr im vector hat viel unnötigen overhead.



  • danke sehr 🙂



  • ok, hab mich doch noch an ne frage erinnert^^

    bzw neue unklarheit:

    BITMAP** frickelig = new BITMAP*[SIZE];
    for (int k=0; k<SIZE; ++k) {
       frickelig[k] = loadbitmap(...);
    }
    for (int k=0; k<SIZE; ++k) {
       delete drickelig[k];
    }
    delete[] frickelig;
    

    verstehe ich das richtig, dass bei nem pointer auf pointer ich echt 2 mal deleten muss?
    Oder würde es auch mit einem "delete[]" ohne die einzelnen deletes vorher funktionieren?


  • Mod

    Du musst genau das deleten, was du vorher mit new angefordert hast. Keine Tricks, keine Ausnahmen.



  • SeppJ schrieb:

    Du musst genau das deleten, was du vorher mit new angefordert hast. Keine Tricks, keine Ausnahmen.

    Naja. So streng würde ich das nicht sagen. Man muss wenigstens wissen, wer es frei gibt (und darauf sollte man sich nur verlassen, wenn es explizit genau so gesagt wird, dass es gemacht wird). Siehe z.B Smart Pointer. Da erzeugst du mit new, gibst es aber explizit nirgends mehr selbst wieder frei mit delete (ist ja genau die Aufgabe des Smart Pointers).



  • kingcools2 schrieb:

    verstehe ich das richtig, dass bei nem pointer auf pointer ich echt 2 mal deleten muss?

    Oder würde es auch mit einem "delete[]" ohne die einzelnen deletes vorher funktionieren?

    Nö. Wieso sollte es? Wenn ein Zeiger zerstört wird (und Du hast hier ja ein Array aus Zeigern) passiert rein gar nichts. Mit Deiner Logik wär auch das delete[] überflüssig und sobald der Zeiger frickelig "stirbt" (zB wenn die Funktion verlassen wird).

    Automatische Müllabfuhr gibt's hier nicht. Du musst Dich schon selbst um den Dreck kümmern. Das heißt aber nicht, dass Du munter new/delete verwenden musst. Du kannst die "Arbeit" deligieren. Schönes Beispiel, aber eigentlich noch Zukunftsmusik: vector<unique_ptr<BITMAP>>.

    Die Idee sollte aber klar sein: Statt manuell aufzupassen, haben wir die "Arbeit" deligiert. Ein unique_ptr fühlt sich verantwortlich für das, worauf er zeigt und löscht das Objekt ggf. Ein Vektor fühlt sich verantwortlich für die Verwaltung seiner Elemente. So kommst Du oft ohne new/delete aus (siehe CptCs Beispiel).

    So etwas ähnliches bekommst Du auch über die Zeiger-Kontainer von Boost. Die fühlen sich auch verantwortlich für die Verwaltung der Elemente.

    Fazit: Es gibt keine automatische Garbage Collection. Was tun? Erst keinen Müll erzeugen und die Verwaltung frühst möglich deligieren.



  • ok, danke schön, dann hab ich das bisher falsch gemacht


Log in to reply