locked
Memory leaks in my application RRS feed

  • Question

  • Hi, i'm using in my app the following code: CDC* pDC and CBitmap* Bitmap, declared in my header file. In my CPP file in OnInitDialog() i use pDC = new CDC and Bitmap = new CBitmap; Of course, these pointer are created but not deleted. When i debug my program it says in output
    {115} client block at 0x02382D50, subtype 0, 8 bytes long.
    a CBitmap object at $02382D50, 8 bytes long


    {114} client block at 0x02382D90, subtype 0, 16 bytes long.
    a CDC object at $02382D90, 16 bytes long


    I've tried to create a destructor, because dialog doesn't have destructor by default but it did not worked(went on showing me that message).
    My destructor was that: My class is called Game . In Game.h i used virtual ~Game(); and in Game.cpp after constructor - Game::~Game() and deleted pDC and Bitmap there;
    Then I tried to use OnDestroy() function by ClassWizard, and typed delete pDC; delete Bitmap; but still no effect.
    How can i avoid these errors? Thanks in advance!
    Saturday, February 20, 2010 4:34 PM

Answers

  • Change your ShowBitmap1()'s second parameter to a pointer like this:

    void Class1::ShowBitmap1(CBitmap *p, CDC* pDC)
    {
       CDC dcMemory;
       BITMAP bm;
       dcMemory.CreateCompatibleDC(pDC);
       dcMemory.SelectObject(p); 
       p->GetBitmap(&bm);
    
       pDC->BitBlt(0, 200, bm.bmWidth, bm.bmHeight, &dcMemory, 0, 0, SRCCOPY);
    
    }
    • Marked as answer by Nancy Shao Monday, March 1, 2010 6:53 AM
    Monday, February 22, 2010 8:14 PM

All replies

  • > Hi, i'm using in my app the following code: CDC* pDC and CBitmap*
    > Bitmap, declared in my header file.

    Why?

    > In my CPP file in OnInitDialog() i
    > use pDC = new CDC and Bitmap = new CBitmap;

    Again, why?

    You normally only have DC objects for a very limited time/scope &
    similarly bitmap objects. You normally create them before you need them
    and destroy them as soon as you've finished with them.

    I suggest that you put your CBitmap object (not a pointer) into your
    dialog class - that way it'll be automatically destroyed when the dialog
    is. For the DC you should limit it's scope to just where it's needed -
    again just use a CDC instance (no new/pointers) local to where you need
    it and the destructor will tidy up when it goes out of scope.

    Dave
    Saturday, February 20, 2010 7:11 PM
  • Ok, thanks for your reply, but i need these pointers in order to draw. My program contains falling stuffs, which are bitmap files. I'm using function to display them. In OnTimer i make them move and then i load the function there, just like:
    OnTimer(UINT nIDEvent)
    {
    ShowBitmap(&bitmap1, pDC);        // where bitmap1 is variable from CBitmap, and the function parameters are CBitmap*,CDC* pDC
    // then p it gets the address of the variable bitmap1 and pDC gets called from pDC, declared in my header file. Simply said i use OnTimer for // drawing.
    }

    If you have any idea how to draw something in OnPaint() (not OnTimer) and it must be re-drawed when the coordinates of the falling stuffs change, and how to make function to load bitmap file and load it without using pointer, please help me. Thanks!
    Saturday, February 20, 2010 7:29 PM
  • In your OnTimer, call Invalidate() and that will cause the OnPaint() function to get called. 

    You can add the CBitmap(not the pointer) as a member variable of your dialog class so you don't need to new it up in the OnInitDialog, just load the bitmap.  Then it will clean up itself.

    Saturday, February 20, 2010 8:13 PM
  • To make a redraw happen call Invalidate().  The OnTimer should just change the coordinates and then call Invalidate.  Then OnPaint will be called and do the drawing with the new coordinates.

     

    Saturday, February 20, 2010 8:15 PM
  • In order OnPaint() to work i must add this two lines at the beggining:

        CPaintDC dc(this); // device context for painting
        dc.BitBlt(0,0,rect.right,rect.bottom,pDC,0,0,SRCCOPY);


    The 5th parameter, where is pDC in my case, it requires a pointer!
    Saturday, February 20, 2010 8:16 PM
  • In order OnPaint() to work i must add this two lines at the beggining:

        CPaintDC dc(this); // device context for painting
        dc.BitBlt(0,0,rect.right,rect.bottom,pDC,0,0,SRCCOPY);


    The 5th parameter, where is pDC in my case, it requires a pointer!

    No, you can use &dc

    Saturday, February 20, 2010 8:24 PM
  • Thanks, but how to call the function ShowBitmap(&bitmap1, pDC);

    bitmap1 is CBitmap variable, and ShowBitmap(CBitmap* p, CDC* pDC) is the declaration.
    Saturday, February 20, 2010 8:25 PM
  • Same idea:

    ShowBitmap(&bitmap1, &dc);

    You do not have to make pointers (and use new/delete) just because a function requires the address of something. You can always take the address of an object with &object

    Saturday, February 20, 2010 10:06 PM
  • When you make a class you should try to make an embedded destructor using the Tilda
    class Pointer
     {
     public:
      Point(float mypoint);
      ~Pointer();

     private:
     protected:
     };
     There is some good C++ tutorials on the "3DBuzz website"
     
    Sunday, February 21, 2010 7:14 AM
  • I made it in this way: Instead of pointer i made it variable - CDC* pDC transformed into CDC pDC; Then instead of pDC i use &pDC.
    And my functions that display bitmaps have parameters: CBitmap* p, CDC pDC; But when i call it says
    cannot convert parameter 2 from 'class CDC' to 'class CDC'

    void Class1::ShowBitmap1(CBitmap *p, CDC pDC)
    {
       CDC dcMemory;
       BITMAP bm;
       dcMemory.CreateCompatibleDC(&pDC);
       dcMemory.SelectObject(p);
       p->GetBitmap(&bm);

       pDC.BitBlt(0, 200, bm.bmWidth, bm.bmHeight, &dcMemory, 0, 0, SRCCOPY);

    }

    Then i call it: ShowBitmap1(&bitmap1, pDC); or ShowBitmap1(&bitmap1, & pDC);
    It didn't work both cases.

    Where am i wrong?
    Monday, February 22, 2010 4:32 PM
  • Put it back the way it was. 

    CPaintDC dc(this);
    ShowBitmap(&bitmap1, &dc);

    You can pass a pointer to any object.  That gives the function access to the original object. But there are many objects that cannot be passed to a function because calling a function requires copying the parameters.  The function receives a copy; not the orignal object. A CPaintDC is not copyable. That is one of the big reasons that the language has pointers.

    Monday, February 22, 2010 5:02 PM
  • OK, but according to the function itself, as you can see it uses a pointer from CBitmap* and this pDC which draws actually the bitmap.
    If i have to use it in OnPaint, shouldn't I change the internal code of the function?
    Because it gives me an error: cannot convert from class CPaintDC to class CPaintDC or i've tried cannot convert from class CDC to class CDC
    Monday, February 22, 2010 6:06 PM
  • Change your ShowBitmap1()'s second parameter to a pointer like this:

    void Class1::ShowBitmap1(CBitmap *p, CDC* pDC)
    {
       CDC dcMemory;
       BITMAP bm;
       dcMemory.CreateCompatibleDC(pDC);
       dcMemory.SelectObject(p); 
       p->GetBitmap(&bm);
    
       pDC->BitBlt(0, 200, bm.bmWidth, bm.bmHeight, &dcMemory, 0, 0, SRCCOPY);
    
    }
    • Marked as answer by Nancy Shao Monday, March 1, 2010 6:53 AM
    Monday, February 22, 2010 8:14 PM
  • Use these two lines to delete the CDC.

     pMDC->DeleteDC();
     delete (pMDC); 

    Below is an extract from a piece of working code with bits removed.  This code writes a bitmap to a memory DC and then saves it to a file.

    CDC *screenDC = TheWindow->GetDC();
     CDC *pMDC = new CDC;
     pMDC->CreateCompatibleDC(screenDC);
    ...
    ... 
      CBitmap *pb = new CBitmap;
     pb->CreateCompatibleBitmap(screenDC, iNewWidth, iNewHeight);
    ...
    ... 
     CBitmap *pob = pMDC->SelectObject(pb);
    ...
    ... 
    CImage CMyImage;
          BOOL bOK = CMyImage.Load(TileFileName);
            if (bOK == S_OK)
            {
       CMyImage.StretchBlt(pMDC->m_hDC,80*loopx,80*loopy, 80, 80, 0, 0, CMyImage.GetWidth(), CMyImage.GetHeight(), SRCCOPY);
           CMyImage.Destroy();
          }
    ...
    ... 
    CImage new_image;
     new_image.Attach((HBITMAP)(*pb));
     strncpy_s(WorkingFolder,300,TileFolder,290);
     strcat_s(WorkingFolder,300....
     new_image.Save(_T(WorkingFolder));
     new_image.Destroy();

     delete (pb);
     screenDC->DeleteDC();
     pMDC->DeleteDC();
     delete (pMDC);          

    Wednesday, May 6, 2015 3:09 PM