Memory Leaks - GDI Objekte mit Create


  • Administrator

    Guten Tag zusammen,

    Mir ist da grad was passiert und ich bin nun vollends am Ende meines Lateins.
    Ich habe eine MDI Anwendung geschrieben, welche auch prima funktioniert. Zumindest beim ersten Dokument. Wenn ich das erste Dokument schliesse und ein zweites erstelle, funktioniert das manchmal auch noch. Wenn das wieder geschlossen wird und ich wieder ein neues erstelle, dann funktionieren die ersten Dinge sicherlich nicht mehr. Die Werte im Hintergrund sind allerdings richtig gesetzt. Aber bei der Ausgabe, also bei OnDraw, fängt der völlig an zu spinnen. So kommt es mal vor, dass ein X irgendwo weit neben der MDI Anwendung auftaucht. Oder auch das Icon irgendwo plötzlich gezeichnet wird. Dabei bin ich in meinem Programm noch gar nicht soweit, dass ich irgendetwas an diesen Einstellungen verändert habe. (MDI Grundgerüst, habe ich natürlich vom Assistenten erstellen lassen). Wenn ich wieder das Dokument schliesse und ein neues eröffne, dann wird es langsam wirklich derb. So habe ich eine Dialogbox am Anfang beim öffnen. Diese erscheint nur noch als graue Box. Die Dinge sind zwar vorhanden, also durch wildes rumgeklicke findet man dann auch diese Checkboxes und Editfelder. Titelleiste und anderes sind dann meisten auch schon ganz verschwunden. Und bei jedem neuen Dokument wird es irgendwie noch schlimmer. Es passiert auch, wenn ich die Dokumente nicht schliesse, sondern einfach immer ein neues erstelle.

    Zudem wird nicht nur das Childframe völlig inkorrekt gezeichnet, sondern auch das Mainframe bekommt Fehler. Hab ehrlich gesagt sowas noch nie gesehen und desweiteren hab ich doch an dem Zeugs gar nichts gemacht, dass kommt doch alles vom Assistenten. Kommt das irgendjemandem bekannt vor? Hat jemand eine Idee, wo ich nachschauen soll? Woran könnte dies liegen?

    Mit Freundlichen Grüssen

    Dravere 😮



  • Du reservierst dir (vermutlich beim Zeichnen) immer mehr Ressourcen, so dass irgendwann keine mehr frei sind. Und dann fängt das an komisch auszusehen.

    Leider weiß ich nicht mehr, welche Befehle da alle dazugehörten...


  • Administrator

    interessant, das würde einen gewissen Zusammenhang bringen mit dem was ich gerade noch rausgefunden habe:
    First-chance exception at 0x77e9bc3f in VerDraHaus.exe: Microsoft C++ exception: CResourceException @ 0x0012f1e4.
    Warning: Uncaught exception in WindowProc (returning 0)

    Anderst gesagt hätte das mit einem Speicherleck zu tun. Hmmm ...
    Dann hätte ich vielleicht eine Idee ...
    Vielen Dank erstmals, ich werde mal dieser Idee nachgehen und danach mich hier wieder melden.
    Grüssli


  • Administrator

    OK die Idee und eine vielzahl anderer Ideen hat bisher nichts gebracht.
    Etwas begreife ich noch nicht ganz. Wenn ich ein Dokument öffne und es dann wieder schliesse, dann sollten doch alle Ressourcen darin verloren gehen, bzw. wieder zur Verfügung stehen. Aber dem scheint gar nicht so zu sein.
    Wäre also dankbar für weitere Hilfe.
    Grüssli


  • Administrator

    Ok hab es gelöst. Falls es jemand interessiert,

    Es ging um GDI Objekte, welche ich mit Create erstellt habe. Also zum Beispiel:

    CFont font;
    font.CreateFont(16,// nHeight
    	       0,// nWidth
    	       0,// nEscapement
    	       0,// nOrientation
    	       FW_NORMAL,// nWeight
    	       FALSE,// bItalic
    	       FALSE,// bUnderline
    	       0,// cStrikeOut
    	       ANSI_CHARSET,// nCharSet
    	       OUT_DEFAULT_PRECIS,// nOutPrecision
    	       CLIP_DEFAULT_PRECIS,// nClipPrecision
    	       DEFAULT_QUALITY,// nQuality
    	       DEFAULT_PITCH | FF_SWISS,// nPitchAndFamily
    	       "Arial");// lpszFacename
    
    // oder direkt zu einem HFONT //
    
    HFONT hfont = CreateFont(16,// nHeight
    	                0,// nWidth
    	                0,// nEscapement
    	                0,// nOrientation
    	                FW_NORMAL,// nWeight
    	                FALSE,// bItalic
    	                FALSE,// bUnderline
    	                0,// cStrikeOut
    	                ANSI_CHARSET,// nCharSet
    	                OUT_DEFAULT_PRECIS,// nOutPrecision
    	                CLIP_DEFAULT_PRECIS,// nClipPrecision
    	                DEFAULT_QUALITY,// nQuality
    	                DEFAULT_PITCH | FF_SWISS,// nPitchAndFamily
    	                "Arial");// lpszFacename
    

    Es spielt dabei keine Rolle welche Art von GDI Objekte. Sobald man sie erstellt hat, muss man sie wieder löschen. Dies geht nicht automatisch. Die Funktion die man dazu aufrufen muss ist folgende:

    DeleteObject(HGDIOBJ hObject);
    

    Ihr findet dazu auch was in der MSDN.

    Beim mir war desweitern noch das Problem, dass ich das Handle gespeichert habe. Und zwar nicht nur eines, sondern ca. an die 200 - 300 Stück in einer Liste. Die meiner Meinung nach Beste Lösung hierbei ist es nicht die Handles zu speichern, sondern die Werte. So zum Beispiel, wieder beim CFont Objekt, gibt es die Struktur LOGFONT. Die könnt ihr ganz einfach mit CFont::GetLogFont(LOGFONT* pLog) holen.

    CFont font;
    LOGFONT lg;
    font.GetLogFont(&lg);
    
    // oder einsetzen //
    font.CreateFontIndirect(&lg);
    
    // dabei am Ende nicht vergessen //
    DeleteObject(font);
    

    Diese Sturkturen sind sowieso viel besser auch zum bearbeiten. In einem LogFont kann man die Grösse einfach ändern, während man bei einem CFont Objekt es so gut wie neu erstellen kann.

    Dies alles gilt wie gesagt für GDI Objekte. Also solche wie CPen, CBrush, CFont, CBitmap, CRgn und CPalette.
    Erstellt sie nur gerade zum zeichnen und löscht sie danach gleich wieder.

    Ich hoffe ich werde ein paar Leuten, welche in die gleiche Sache hineinlaufen damit helfen können ^^'

    Grüssli

    PS: Danke estartu für die einzige Hilfe 😉



  • Ich danke dir für die schöne Erklärung. 👍 🙂


Anmelden zum Antworten