Speicherverwaltung



  • Das ist genau das, was ich suche!

    Ich hab mir das auch gestern Abend schon im Lehrbuch durchgelesen, aber eine
    Frage hab ich noch: Wenn ich jetzt einen auto-pointer zurück geben will,
    muss ich den doch auch mit new erzeugen und habe dann den im Speicher
    rumgammeln.

    Am meisten würde mir ein Beispiel helfen. Wie löse ich folgende Ausgabe
    mit auto-pointern? Es soll inkrementell die endgültige Lösung bestimmt
    werden, indem geprüft wird, ob die Lösung vollständig ist und falls nicht
    ein weiteres Element der Lösung gesucht wird.
    Brauche ich jetzt einen Vektor von auto_pointern?

    main(){
     vector<vector<int> > *m = new vector<vector<int> >;
    
     while(istNichtLoesung(m)){
      v.push_back(berechneNeuesElement(m));
     }
    }
    
    vector<int> *berechneNeuesElement(vector<vector<int> > *m){
     vector<int> *returnVektor = new vector<int>;
     //returnVektor in Abhängigkeit von m bestimmen;
     return returnVektor;
    }
    


  • 1.) Verlassen auto_ptr den Gültigkeitsbereich wird der delete für den Pointer
    aufgerufen. Grade das ist ja der Trick. Das heisst, du machst igendwann dein
    new und der auto_ptr macht das zugehörige delete.
    2.) auto_ptr vetragen sich NICHT mit STL-Containern, wegen der Besonderheiten
    bezüglich "Copy" und "Assignment". Daher KEINE auto_ptr in STL-Containern
    verwenden. Willst du Smart-Pointer in STL-Containern, dann verwendest
    du am besten was von boost.



  • Chew-Z schrieb:

    2.) auto_ptr vetragen sich NICHT mit STL-Containern, wegen der Besonderheiten
    bezüglich "Copy" und "Assignment".

    Vielleicht könntest du die besonderheit das nächste mal auch erwähnen.
    std::auto_ptr<>

    C++ Standard 20.4.5, p3 schrieb:

    "auto_ptr does not meet the CopyConstructible and Assignable requirements..."

    Die Container verlangen aber gerade diese eigenschaft von objekten die in ihnen gespeichert werden sollen.
    Das ist der selbe Grund weshalb man std::auto_ptr<> auch nicht mit std::swap benutzen kann. Aber das ist ein anderes Thema.

    Chew-Z schrieb:

    Daher KEINE auto_ptr in STL-Containern
    verwenden. Willst du Smart-Pointer in STL-Containern, dann verwendest
    du am besten was von boost.

    Da kann ich nicht widersprechen, aber man sollte sich gut überlegen ob man so viele SmartPointer benutzen möchte denn man sollte daran denken auch ein SmartPointer kostet Arbeitsspeicher. 🙄

    MfG



  • Was auch ein Grund fuer Speicherlecks sein kann, ist, wenn Du bei std::vector vergisst, push_back() zu machen, um das Array zu vergroessern, bevor Du operator[] benutzt. Dann machst Du naemlich die Speicherliste kaputt. 😉



  • Power Off schrieb:

    Was auch ein Grund fuer Speicherlecks sein kann, ist, wenn Du bei std::vector vergisst, push_back() zu machen, um das Array zu vergroessern, bevor Du operator[] benutzt. Dann machst Du naemlich die Speicherliste kaputt. 😉

    😕 😕 😕 😕

    😮 😮 😮 😮

    Du solltest mal überlegen was du da eben von dir gegeben hast.

    MfG



  • eViLiSSiMo schrieb:

    😕 😕 😕 😕

    😮 😮 😮 😮

    Du solltest mal überlegen was du da eben von dir gegeben hast.

    MfG

    vector<T>::operator[] vergroessert ein Array nicht.

    Laut Spezifikation liefert es eine Referenz auf ein Array-Element, der Index wird jedoch nicht auf Korrektheit geprueft, das macht vector<T>::at().

    vector<T>::push_back() fuegt ein Element am Ende eines Array hinzu, und vergroessert es, wenn notwendig.

    Die Speicherliste kann betroffen sein, wenn die Speicherverwaltung so funktioniert:

    <pointer to next element>
    <size of memory block>
    ... data ...
    <pointer to next element>
    <size of memory block>
    ... data ...
    

    Schreibt man ueber den Anfang oder das Ende eines Arrays hinaus, kann dadurch der Zeiger auf das naechste Element ueberschrieben werden.

    Probier mal folgendes:

    #include <vector>
    
    typedef std::vector<int> IntVec;
    
    int main( int argc, char** argv ) {
       IntVec v;
       v[-2] = 0XABCDEF01;
       v[-1] = 0X12345678;
       v[ 1] = 0X87654321;
       v[ 2] = 0XFEDCBA98;
       return 0;
    }
    

    Das kann zu einem Absturz fuehren, wenn die Speicherliste keinen Platz rund um den zugewiesenen Speicher hat.

    Es kann auch zu einem Speicherleck fuehren, wenn Zeiger der Speicherliste betroffen sind, oder das Laengenfeld im Speicherblock.



  • LOL Du Held.

    Man füllt einen std::vector<> nicht mit dem operator[]
    Laut Standard ist für den operator[] keinen Range check vorgeschrieben das heißt es gibt keine Exceptions und du kannst "einfach so" da machen was du willst.

    Die Methode at() hingegen muss schon einen range check machen.

    C++ Standard 23.1.1 p 13 schrieb:

    The member function at() provides boundschecked access to container elements. at() throws out_of_range if n >= a.size().

    🙄 🙄 🙄 🙄 🙄 🙄 🙄

    Und nun der oberhammer:

    g++ 3.4.4 schrieb:

    stdvec.cc: In function int main(int, char**)': stdvec.cc:7: warning: passing negative value-0x00000000000000002' for converting 1 of typename \_Alloc::reference std::vector<\_Tp, \_Alloc>::operator[](size\_t) [with \_Tp = int, \_Alloc = std::allocator<int>]' stdvec.cc:8: warning: passing negative value-0x00000000000000001' for converting 1 of `typename _Alloc::reference std::vector<_Tp, _Alloc>::operator[](size_t) [with _Tp = int, _Alloc = std::allocator<int>]'

    Das sollte mir zu denken geben. An deiner stelle würde ich mich mal genauer mit dem befassen. Anstatt hier einfach irgendwelche behauptungen auf zu stellen.

    MfG 🙄



  • Ja ja, das sind aber nur Compiler-Warnungen, uebersetzt wird es trotzdem.
    Und das mit dem operator[] habe ich ja bereits oben geschrieben:

    [quote=Power Off]
    vector<T>::operator[] vergroessert ein Array nicht.

    Laut Spezifikation liefert es eine Referenz auf ein Array-Element, der Index wird jedoch nicht auf Korrektheit geprueft, das macht vector<T>::at().
    [/quote]

    Lesen muesste man halt koennen, gell!



  • lol.

    Hach ja
    Lesen sollte man echt können.

    Ich hab die ganze Zeit gedacht du gehst davon aus das man mit dem op[] auch speicher allokieren könnte ^^

    sry mein fehler 🙄



  • Danke schonmal für die motivierten Antworten soweit, zwei Fragen hab ich noch:
    1. Sind Speicherlecks nur während der Ausführungszeit meines Codes relevant und
    werden danach "von alleine" entfernt? z.B. vom Betriebssystem
    2. Mir ist immer noch nicht klar, wie ich den smart-pointer dann verwende,
    ohne dass mein Problem sich verschiebt und ich hinterher zusehen muss, dass
    der pointer gelöscht wird. (das Objekt wird gelöscht, klar - aber der Zeiger?)



  • raphael2 schrieb:

    1. Sind Speicherlecks nur während der Ausführungszeit meines Codes relevant und
    werden danach "von alleine" entfernt? z.B. vom Betriebssystem

    jo, das os gibt alles wieder frei wenn dein programm nicht mehr läuft



  • Chew-Z schrieb:

    1.) Verlassen auto_ptr den Gültigkeitsbereich wird der delete für den Pointer
    aufgerufen. Grade das ist ja der Trick. Das heisst, du machst igendwann dein
    new und der auto_ptr macht das zugehörige delete.
    2.) auto_ptr vetragen sich NICHT mit STL-Containern, wegen der Besonderheiten
    bezüglich "Copy" und "Assignment". Daher KEINE auto_ptr in STL-Containern
    verwenden. Willst du Smart-Pointer in STL-Containern, dann verwendest
    du am besten was von boost.

    Wer lesen kan ist klar im Vorteil. 😃

    Siehe Punkt 1



  • Bin evtl. etwas langsam, aber jetzt erkläre ich meine Frage nochmal, vielleicht kapier ichs ja noch:

    Ich habe also diese Methode, die für mich rechnet:

    static set<int> *berechnung(vector<vector<int> > *data){
      set<int> *erg = new set<int>;
     //rechnen
    return erg;
    

    dann habe ich eine Schleife, die diese Methode aufruft, bis keine
    neuen Ergebnisse mehr geliefert werden:

    vector<vector<int> > *myData;
    //myData wird initialisiert und gefüllt
    
    while(unfinished()){
     mySet.insert(berechnung(myData)
    }
    

    Jetzt wurde vorgeschlagen, ich gebe anstatt dessen einen auto_pointer
    zurück, meine Methode muss doch aber trotzdem diesen autopointer mit
    new initialisieren, ungefähr so:

    auto_prt<set<int> berechnung{
      auto_ptr<set<int> > ret( new set<int> );
      //berechnung...
      return ret;
    }
    

    damit ist der auto_ptr nach Rückgabe schon nichtmehr gültig.
    Anders müsste ich ihn mit new erstellen:

    ...
    auto_ptr<set<int> > ret = *(new auto_ptr<set<int> >(new set<int>));
    //berechnung...
    return ret
    

    und jetzt habe ich vielleicht ein kleineres Speicherleck (nur ein Pointer)
    aber das kann ja nicht die Idee sein.

    Danke soweit.



  • Ich habe eine Webpage gefunden, die den Mechanismus unterschiedlicher Besitzer bei auto-pointern erklärt und damit hat sich auch die Frage erledigt.

    Grüße, Raphael


Anmelden zum Antworten