delete[], delete????



  • Doch was passiert, wenn ich ein new[] mit delete lösche?

    Ist undefiniert.

    Nun habe ich anfänglich beide Objekte (Objekt der Klasse und das Objekt,welches den Rückgabewert aufnimmt) in "OnDblclkAuftragsbox()" durch ein delete[] gelöscht. Dabei kam es zu Speicherfehlern.
    Entferne ich bei beiden deletes die Klammern, so ist der Speicherfehler nicht mehr da.
    Was mich nun verwundert ist die Tatsache, dass ich die Klammern beim delete des Klassenobjektes wieder einfügen kann ohne das es knallt.

    Beim delete([]) knallts eigentlich nur wenn was mit dem spreicherblock nicht stimmt (du hast drüber hinaus geschrieben, ungülitger pointer, ..)



  • Sorry CMatt,

    könntest Du das mal näher ausführen? Ich verstehe 😮 nix...

    Mit undefiniert meinst DU, dass ich Speicher nicht freigebe??

    Es ist so, dass ich ein mit new erstelltes Objekt einerseits mit delete[] löschen kann ohne das es einen Fehler gibt(wie in obigen Beispiel) und ein anderes Mal gibt es einen Speicherfehler und es funktioniert nur, wenn ich mit einfachem delete lösche.



  • Mit undefiniert meinst DU, dass ich Speicher nicht freigebe??

    Mit undefiniert meint er das alles mögliche passieren könnte. Es könnte der Speicher freigegeben werden, er könnte es nicht. Es könnt etwas völlig anderes passieren.



  • Das heißt manchmal gehts gut und das Programm läuft scheinbar Fehlerlos und das andere Mal gibts Speicherfehler???
    Warum motzt der Compiler nicht direkt, dass es Verkehrt ist?



  • Woher soll das compiler das wissen?
    Versuch mal compiler zu spielen:

    char *p;
    
    if(rand()%10 < 5)
     p = new char[100];
    else 
     p = new char;
    
    delete p; // hmmm... was nehemn wir jetzt? delete oder delete[]
    

    :p

    Das heißt manchmal gehts gut und das Programm läuft scheinbar Fehlerlos und das andere Mal gibts Speicherfehler???

    Wie oben geschrieben, das liegt an dir nicht am compiler. delete[] ist richtig, delete ist falsch, wenns mit delete[] knallt, dann kannst du nicht aufs falsche delete ausweichen sonern musst den Fehler finden.
    Bsp. du schreibst irgendwo über den speicher hinaus und machst dir damit das letzte element in deinem array kaput. delete macht irgend was, und das irgend was führt nicht dazu das dein letztes elemnt gelöscht wird => alles läuft (wie bei dir). delete[] gibts alle elemnte frei => beim letzten knallts weil das kaput ist.



  • Wie oben geschrieben, das liegt an dir nicht am compiler. delete[] ist richtig, delete ist falsch ...

    Hmmm.... auf was beziehst Du Dich nun?

    Muss ich folgendes nicht mit delete anstatt mit delete[] löschen??

    CSpezialFunktionen* Projekt = new CSpezialFunktionen;
    


  • Hmmm.... auf was beziehst Du Dich nun?

    ->

    Beim delete([]) knallts eigentlich nur wenn was mit dem spreicherblock nicht stimmt (du hast drüber hinaus geschrieben, ungülitger pointer, ..)

    Muss ich folgendes nicht mit delete anstatt mit delete[] löschen??

    jo

    new ==> delete
    new[] == delete[]



  • Beim delete([]) knallts eigentlich nur wenn was mit dem spreicherblock nicht stimmt (du hast drüber hinaus geschrieben, ungülitger pointer, ..)

    Ooooh man, habe mich ein wenig von meinem Rechner wegbewegt und den Satz dann zum xten Mal angeschaut. Und siehe da: jetzt wird mir der Sinn klar. Ich hatte ihn zuvor ganz anders verstanden. Irgendwie fehlt mir da ein "z.B." in der klammer. Hatte es so verstanden als läg da mein Fehler und nicht als allgemeinen Satz. Ist eine harte Woche ... 🙄



  • da fehlt kein z.b, sondern ich war einfach zu fault "delete oder delete[]" zu schreiben :p



  • Die Erklärung mit dem "char *p" war übrigens sehr einleuchtend.

    Doch schaut Euch bitte mal meinen Code genauer an. Ich denke mein Fehler liegt darin, dass ich den Speicher fürs Array im Destructor lösche. Kann es sein, dass ich die Sache mit den Pointern falsch angehe?

    Hättet Ihr da eine bessere Idee?



  • z.B. => 2te Klammer!! 😉



  • Hi, ein paar vorschläge von mir....

    class CSpezialFunktionen : public CDialog // warum ?? ist das nötig?
                                              // ansonsten weg damit und vielleicht eine Singletonklasse von machen!
    { 
    public: 
        CString* m_Array; // braucht man nicht => weg damit (ist deine Speicherverletzung!)
        CString* DateiHolen(CString Datei, int &anzahl); 
    
        CSpezialFunktionen(CWnd* pParent = NULL);   // standard constructor 
        ~CSpezialFunktionen(); 
    }; 
    
    CSpezialFunktionen::~CSpezialFunktionen() 
    { 
        delete[]m_Array; // auch wech damit *puff*
    } 
    
    CString* CSpezialFunktionen::DateiHolen(CString Datei, int &anzahl) 
    { 
        CString* pArray = new CString[5]
        //m_Array = new CString[5]; 
    
        ///////////////////////////////////hier wird m_Array befüllt//////////////////////////// 
    
        //return m_Array; 
        return pArray;
    } 
    
    #include "Spezialfunktionen.h" 
    
    void COffeneJobsWahl::OnDblclkAuftragsbox() 
    { 
        int anzahl = 0; 
        CSpezialFunktionen* Projekt = new CSpezialFunktionen; // wäre bei Singleton nicht nötig und spart Zeit bzw. Resourcen
        //CString *ArrayProjekt; 
    
        CString* pArrayProjekt = Projekt->DateiHolen(C:\\egal.txt, anzahl);    
    
        delete []pArrayProjekt; 
        delete Projekt; // fällt auch raus bei Singleton
    }
    

    Wenn du das array in OnDblclkAuftragsbox löscht und dann das Projekt löscht,
    löscht du das Objekt zweimal (s. Destruktor in der Spezialklasse) ! Das kann nicht gut gehen.

    Singleton würde ich mir mal anschauen: http://gethelp.devx.com/techtips/cpp_pro/10min/10min0200.asp



  • void COffeneJobsWahl::OnDblclkAuftragsbox() 
    { 
        int anzahl = 0; 
        CSpezialFunktionen* Projekt = new CSpezialFunktionen; 
        CString *ArrayProjekt; 
        // soweit alles klar
    
        // DateiHolen macht ein new CString[5] und gibt nen pointer zurück
        ArrayProjekt = Projekt->DateiHolen(C:\\egal.txt, anzahl);    
    
        // du löscht dein string array 
        // Fehler: es ist ein array also delete[]
        delete ArrayProjekt; 
    
        // du löscht dein CSpezialFunktionen obejct
        // 1. Fehler: es ist ein einzelnes object also delete
        // 2. Fehler: der destroctur von CSpezialFunktionen mach ein 
        //            delete auf ein string-array, das gibts aber mitlerweile
        //            nimmer da du bereits selbst delete ArrayProjekt aufgerufen
        //            hast
        delete []Projekt; 
    }
    

    Anmrekungen:
    - Was macht der construtor von CSpezialFunktionen? Setzt der m_Array auf 0? Falls nicht knallts sollest du mal irgendwann DateiHolen nicht aufrufen (ein delete[] call auf nen pointer ins nirvana)
    - Wenn du beim delete im destructor bleist. Was passiert wenn du DateiHolen öfter aufrufst? Zur zeit: speicherleck.



  • Boa, viele Infos auf einmal!

    habe gleich Feierabend und schaff leider nicht mehr alles.
    Werde Montag voll dran gehen und alles aufarbeiten.
    Singleton ist mir völlig unbekannt, hört sich aber auf den ersten Blick (Threat, etc...) gut an.
    Danke!!

    Aber eine Frage habe ich jetzt noch ...

    // du löscht dein string array
    // Fehler: es ist ein array also delete[]
    delete ArrayProjekt;

    Warum handelt es sich hierbei um ein Array? Der Name ist nur willkürlich.

    CString *ArrayProjekt;

    Die Sache mit den Mehrfachaufrufen der Klasse und denn Speicherlecks dadurch ist sehr informativ, sowie die Sache mit dem Objekt erstellen ohne Speicher zu besorgen bevor ich versuche sie im Destruktor zu löschen.

    Sehr informativ!!

    Schönes Wochenende und bitte noch die eine Frage beantworten 😃



  • Das ArrayProjekt ein Array ist, sieht man nur weil es im Code so geschrieben ist.

    CString* CSpezialFunktionen::DateiHolen(CString Datei, int &anzahl) 
    { 
        CString* pArray = new CString[5] // erzeuge array of CString
        //m_Array = new CString[5]; 
    
        ///////////////////////////////////hier wird m_Array befüllt//////////////////////////// 
    
        //return m_Array; 
        return pArray; 
    }
    

    Der Aufrufer kann das nicht wissen, genausowenig wie das er den Speicher
    freigeben muss und das auch noch mit der delete[] Anweisung.

    Ich habs mal so gelassen, um nicht zu viel auf einmal zu ändern,
    aber Du merkst schon, das hier ein designproblem vorliegt.

    Du könntest ja vielleicht ein CPtrArray zurückliefern...



  • Guten Morgen,

    genau da liegt mein Problem!!!
    Ist ein einfacher CString Pointer automatisch ein CString Array Pointer sobald dieser durch einen Rückgabewert ein solches übergeben bekommt?

    Hmmmmm ... schwer zu erklären!!!
    Also: In der Methode "DateiHolen" lege ich ein CString Array "p_Array" an. Dieses gebe ich per Return zurück auf meinen CString Pointer "ArrayProjekt".
    Ist nun automatisch "ArrayProjekt" dadurch auch ein ArrayPointer?

    Denn p_Array wollte ich ja ursprünglich extra im Destructor löschen und dann denn Zeiger "ArrayProjekt" mit einfachem delete.

    Weil wie ihr sagt werden einfache mit delete und Arrays mit delete[] gelöscht.

    Und wenn es nun so ist, muss ich dann nur "ArrayProjekt" löschen oder doch beide?



  • Wie wäre es denn damit

    CString* pArray = new CString[5] 
    
    //Freigabe
    if(pArray!=NULL)
       pArray=NULL;
    
    delete [] pArray;
    

    oder habe ich was übersehen



  • Cool!! So habe ichs dann auf Anraten eines anderen users (PocketPC Forum)gemacht. Warst ein wenig langsam 😃

    Dennoch danke!!!!



  • Du weißt aber schon das es dafür was in der MFC gibt. Ein CString-Array nent sich da dann auch

    class CStringArray

    Da muss man sich nicht um solche Dinge wie SPeicher freigeben kümmern und auch noch Zeit kosten.

    Du legst 5 Klasseninstanzen von CString an. Weiß jetzt zwar nicht wie es CStringArray intern macht aber IMHO ist da nur eine Klasseninstanz nötig.

    Und willst du dann nochmehr gibt es CMap.
    u.s.w.
    Ist alles besser als ein Array von CString-Klassen.
    CString ist keine Variable sondern eine Klasse.



  • Das ist eigentlich gar kein schlechter Tip!!
    HAtte auch schonmal was davon gehört und doch wieder verdrängt. Schade eigentlich ...
    Werde in Zukunft öfter dran denken.

    THX!!


Anmelden zum Antworten