Speicherplatz steigt bis absturz



  • Hi,

    Ich habe in meinem Programm ein Speicherleck entdeckt, nur weiß ich es abdichte.

    Programminfo:
    Mein Programm liest daten vom USB und macht daraus eine Fluss-Grafk. Der Speicherverbrauch steigt mit jedem Zyclus um ca. 20kb (zu sehen im Taskmanager) und es ist mit 30% CPU-Auslastung auch nicht res-schonend.

    Ich räum aber immer brav alles am Ende der Funktion auf. Das alles wird alle 50ms in einem Timer ausgeführt (das zeichnen natürlich in der OnPaint) und am ende des Timers mach ich ein Invidiate(FALSE);

    CDC cDC;
    	CBitmap cBitmap;
    	CDC* pDC = this->GetDC();
    	CBrush myBrush;
    	CPen cPen;
    	CPen dPen;
    	CPen tLine;
    	CFont cFont;
    	CString string;
    
    	//Create a bitmap and set the options
        cDC.CreateCompatibleDC(pDC);
        cDC.SetBkColor(RGB(255, 255, 255));
        cBitmap.CreateCompatibleBitmap(pDC, 1000, 650);
    
    	//Set Color für brush
    	myBrush.CreateSolidBrush(RGB(255, 255, 255));
    
    	//Select the bitmap and write into it
    	cDC.SelectObject(&cBitmap);
    	cDC.SelectObject(&myBrush);
    
    	//Set font
    	cDC.SetTextColor(RGB(0,0,0));
    	cDC.SetBkMode(TRANSPARENT);
    
    	//Create backgroundcolor for bitmap
    	cDC.FillRect(CRect(0, 0, 1000, 650), &myBrush);
    
    	/*Draw Frame*/
            //Zeichnen
            //......
    
    	/*Draw cBitmap on Screen*/
    	pDC->BitBlt(5, 5, 1000, 650, &cDC, 0, 0, SRCCOPY);
    
    	DeleteDC(cDC);
    	DeleteObject(cPen);
    	DeleteObject(dPen);
    	DeleteObject(tLine);
    	DeleteObject(myBrush);
    	DeleteObject(cBitmap);
    	DeleteObject(cFont);
    

    Das einzige, was ich nicht abräume ist "pDC" (weil keine ahnung wie).
    Gibt es eine möglichkeit den Speicherverbrauch in der Funktion durchzusteppen?

    Danke



  • Die Allokationen stammen aus AfxSocketInit (sockcore.cpp)

    //BLOCK: setup maps and lists specific to socket state
    	{
    		_AFX_SOCK_THREAD_STATE* pState = _afxSockThreadState;
    		if (pState->m_pmapSocketHandle == NULL)
    			pState->m_pmapSocketHandle = new CMapPtrToPtr;
    		if (pState->m_pmapDeadSockets == NULL)
    			pState->m_pmapDeadSockets = new CMapPtrToPtr;
    		if (pState->m_plistSocketNotifications == NULL)
    			pState->m_plistSocketNotifications = new CPtrList;
    	}
    

    Wird Dein Programm vielleicht nicht ordnungsgemäß beendet?



  • Hmmm, mir fällts auf, daß Du mit den Funktionen DeleteDC und DeleteObject nicht in der Reihenfolge freigibst wie Du die Objekte generiert hast.

    Also ich würde immer so machen (nur ein einfaches Beispiel):

    //Erzeuge verschiedene Objekte:
    cDC.CreateCompatibleDC(pDC);
    cBitmap.CreateCompatibleBitmap(pDC, 1000, 650);
    CreateFont(cFont);
    //..
    //..
    
    //Und nun Aufräumen in umgekehrter Reihenfolge:
    DeleteObject(cFont);
    DeleteObject(cBitmap);
    DeleteDC(cDC);
    

    Martin



  • sry, hab den Beitrag bearbeitet...

    Zum Aufräumen:
    Hab deinen Tipp mal umgesetzt. Leider hat das keinen Nennenswerten Unterschied gebracht. Der Speicherverbrauch steigt immernoch genauso schnell und stetig.

    Was ich noch mache ist z.B.:

    /*Draw Baselines*/
    	//**************************************************************************
    	cPen.CreatePen(PS_SOLID, 1, RGB(0,0,0));
    	cDC.SelectObject(&cPen);
    
    	cDC.MoveTo(0, 225);
    	cDC.LineTo(1000, 225);
    
    	cDC.MoveTo(0, 425);
    	cDC.LineTo(1000, 425);
    
    	cDC.MoveTo(0, 625);
    	cDC.LineTo(1000, 625);
    
    	cPen.DeleteObject();
    	//**************************************************************************
    

    Sprich ich räume nach gebrauch gleich alles was ich gebraucht habe weg.



  • Kann es sein, dass die von cDC selektierten Objekte wieder zurückgegeben werden müssen, bevor du den DC löschst? (Bin mir nicht sicher, halt noch Anfänger 😉 )

    Also bei SelectObject zB:
    CBrush* pOldBrush = cDC.SelectObject(&deineBrush);

    und nach dem BitBlt dann:

    cDC.SelectObject(pOldBrush);



  • Djura schrieb:

    Kann es sein, dass die von cDC selektierten Objekte wieder zurückgegeben werden müssen, bevor du den DC löschst? (Bin mir nicht sicher, halt noch Anfänger 😉 )

    Also bei SelectObject zB:
    CBrush* pOldBrush = cDC.SelectObject(&deineBrush);

    und nach dem BitBlt dann:

    cDC.SelectObject(pOldBrush);

    Ja, vor dem Löschen muss das Objekt aus dem DC herausgewählt werden. Zudem wird pDC nicht mit ReleaseDC freigegeben.

    CDC cDC;
        CBitmap cBitmap;
        CDC* pDC = this->GetDC();
        CBrush myBrush;
        CPen cPen;
        CPen dPen;
        CPen tLine;
        CFont cFont;
        CString string;
    
        //Create a bitmap and set the options
        cDC.CreateCompatibleDC(pDC);
        cDC.SetBkColor(RGB(255, 255, 255));
        cBitmap.CreateCompatibleBitmap(pDC, 1000, 650);
    
        //Set Color für brush
        myBrush.CreateSolidBrush(RGB(255, 255, 255));
    
        //Select the bitmap and write into it
        CBitmap* pOldBitmap = cDC.SelectObject(&cBitmap);
        CBrush* pOldBrush = cDC.SelectObject(&myBrush);
    
        //Set font
        cDC.SetTextColor(RGB(0,0,0));
        cDC.SetBkMode(TRANSPARENT);
    
        //Create backgroundcolor for bitmap
        cDC.FillRect(CRect(0, 0, 1000, 650), &myBrush);
    
        /*Draw Frame*/
            //Zeichnen
            //......
    
        /*Draw cBitmap on Screen*/
        pDC->BitBlt(5, 5, 1000, 650, &cDC, 0, 0, SRCCOPY);
    
        cDC.SelectObject(pOldBitmap);
        cDC.SelectObject(pOldBrush);
    
        DeleteDC(cDC);
    
        /* Kann man sich eigentlich sparen, da die Objekte im jeweiligen Destruktor freigegeben werden
        DeleteObject(cPen);
        DeleteObject(dPen);
        DeleteObject(tLine);
        DeleteObject(myBrush);
        DeleteObject(cBitmap);
        DeleteObject(cFont); 
    */
    
        ReleaseDC(pDC);
    


  • Danke !!!
    Jetzt läufts ohne Nennenswerten Speicheranstieg. Das rettet mir meine Nachmittag und ich kann endlich weiterarbeiten.

    👍 👍 👍


Log in to reply