Befreien von Spiecher schlägt fehl



  • Hi an alle,

    folgendes Problem.
    Ich initialisiere mit new ein Array

    LPOLESTR lpMicGuid = new WCHAR[39];
    

    und arbeite damit.
    Nach dem ich es nicht mehr brauche will ich es mit delete löschen
    und bekomme vom compiler gesagt:
    Windows has triggered a breakpoint in DvVoipClient.exe.

    This may be due to a corruption of the heap, and indicates a bug in DvVoipClient.exe or any of the DLLs it has loaded.

    The output window may have more diagnostic information

    Wenn ich aber kein Delete aus führe wird mir im Debug Modus ein
    Speicherleck an dieser stelle angezeigt.

    Wie befreie ich denn den reservierten Speicher nun??

    Gruß
    Crazy



  • Du solltest mal allen relevanten Code zeigen. Vermutlich machst du zwischen new und delete irgendwas böses mit dem Speicher...



  • Das kann natürlich sein.

    Hier der gesamte Code

    LPOLESTR lpMicGuid = new WCHAR[39];
    lpMicGuid = A2OLE(pVal);
    GUID guid;
    CLSIDFromString(lpMicGuid, &guid);
    m_lpGuidMic = (LPGUID)malloc(sizeof(GUID));
    memcpy(m_lpGuidMic, &guid, sizeof(guid));
    if(lpMicGuid != NULL)
    {
         delete lpMicGuid;
         lpMicGuid = NULL;
    }
    


  • delete[]



  • Nein trotzdem der selbe Fehler.



  • Trotzdem musst du immer die richtige Variante benutzen (delete und delete[] sind ein Unterschied, siehe MSDN).

    Warum verwendest du eigentlich abwechselnd new und malloc? Kann man zwar machen, aber du könntest deinen malloc-Aufruf genausogut durch new ersetzen und somit einheitlich bleiben...



  • CrazyPlaya schrieb:

    LPOLESTR lpMicGuid = new WCHAR[39];
    lpMicGuid = A2OLE(pVal);
    

    Und hier ist der mit new geholte Speicher schon nicht mehr erreichbar, weil der Zeiger nun auf den Rückgabewert von A2OLE zeigt.



  • Eieieiei....

    // LPOLESTR lpMicGuid = new WCHAR[39];
    // lpMicGuid = A2OLE(pVal); // falsch, überschreibt den Zeiger "lpMicGuid", der somit nichtmehr auf den neu angeforderten Bereich zeigt,
                                // sondern auf einen Temporären Bereich der vom Makro A2OLE irgendwie herbeigezabuert wird
    // besser & einfacher:
    std::wstring micGuidString = A2OLE(pVal);
    
    // wieso so kompliziert?
    // GUID guid;
    // CLSIDFromString(lpMicGuid, &guid);
    // m_lpGuidMic = (LPGUID)malloc(sizeof(GUID)); // wieso malloc?
    // memcpy(m_lpGuidMic, &guid, sizeof(guid));
    m_lpGuidMic = new GUID; // muss dann natürlich auch mit delete wieder freigegeben werden
    CLSIDFromString(micGuidString.c_str(), m_lpGuidMic);
    
    // fertig.
    
    // brauchen wir jetzt nimmer, std::wstring räumt sich selbst auf
    // if(lpMicGuid != NULL)
    // {
    //      delete lpMicGuid;
    //      lpMicGuid = NULL;
    // }
    

    Und... wieso muss m_lpGuidMic überhaupt ein Zeiger sein? Ein einfaches Nicht-Zeiger-Member ("GUID m_micGuid;") würde reichen. Oder ggf. ein boost::scoped_ptr<GUID> oder std::auto_ptr<GUID>.



  • @MFK: Stimmt, dann brauch ich den ja gar nicht mehr mit new initialisieren.

    @_matze: Hast du schon recht. Die Abwechslung zwischen new und malloc kommt vom Copy and Paste:D:D.
    lalala 😃



  • Dann hab ich gleich noch eine Frage zur Speicherverwaltung.

    ich habe eine Thread, dem ich über eine Struktur einen Zeiger auf eine Klasse übergebe.
    Z.B. so

    MyClass myClass = new MyClass();
    TPARAM tParam;
    tParam.CMyClass = myClass;
    hThread = CreateThread(NULL, 0, &MyThread, &tParam, 0, &dwThreadId);
    

    Und hier der Thread
    DWORD WINAPI CMyClass::MyThread(PVOID pParam)
    {
    TPARAM* tParam = (TPARAM*)pParam;
    CMyClass* myClass = pParam->myClass;
    }

    Wie bereinige ich hier am Ende am besten meinen Speicher?



  • Kannst du die Instanz deiner Klasse nicht direkt im Thread erzeugen (und da wieder freigeben)? Du erzeugst ja sowieso erst kurz vorher eine neue Instanz. Oder wird die später noch gebraucht? Dann sollte das Freigeben vermutlich nix mi dem Thread zu tun haben...



  • Ich benötige die Instanz der Klasse bereits vor dem Threadaufruf.



  • delete myClass;
    

    oder

    delete pParam->myClass;
    


  • Dann kann ich aber nach Abarbeitung des Threads nicht mehr mit der Instanz der Klasse weiterarbeiten.



  • CrazyPlaya schrieb:

    Dann kann ich aber nach Abarbeitung des Threads nicht mehr mit der Instanz der Klasse weiterarbeiten.

    Du hattest auch nicht erwähnt, dass du das musst.
    Stell doch erst mal die Anforderungen auf, anstatt die Helfer vor die Wand laufen zu lassen.



  • Ja, dann war dein Beispiel falsch. Da hast du nämlich eine frisch erzeugte Instanz and den Thread übergeben. So aber hat doch das Freigeben gar nix mit dem Thread zu tun. Dort ist die Instanz nur ein durchlaufender Posten.



  • @MFK: Sorry, mein Fehler. Hats recht hätte ich erwähnen müssen.

    @_matze: Das hab ich auch gedacht, aber irgendwo bleibt noch ein Speicherleck, in dem der Inhalt ist, welcher in dem Thread generiert wird.
    Daher habe ich angenommen dass innerhalb des Threads noch etwas nicht korrekt freigegeben wird.



  • Du solltest einfach genau ein new und ein delete aufrufen. Dann sollte nix schiefgehen. Was macht denn der Thread? Weist du da noch mal Speicher zu oder machst sonstige krumme Sachen?



  • Ja so mach ich es ja bereits. Bevor ich den Thread aufrufe wird die Klasse instanziiert und dann bearbeitet. Dann Thread abarbeiten, hier wird kein neuer Speicher zugewiesen. Dann wird weiter mit der Instanz gearbeiten und beim Beenden wird ein delete ausgeführt.



  • Hast du das mal mit Breakpoints überprüft? Passiert das auch, wenn du sämtliche Bearbeitungen auskommentierst (also nur new+delete)?


Anmelden zum Antworten