• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 534
  • Last Modified:

GDI leak question.

I have an windows mobile app and i'm trying to track down why my app 'freezes' from time to time.  It happens after many hours of use and I dont know why.  I am going over every piece of code and inspecting it to see if I can find the problem.

In the OnPaint() of one of my dialogs I have the following code:

      CBitmap bmp;
       BITMAP bi;
       CClientDC dc(this);
       CDC bmDC;
       bmp.LoadBitmap(IDB_MYBITMAP);
       bmDC.CreateCompatibleDC(&dc);
       CBitmap *pOldbmp = bmDC.SelectObject(&bmp);
       bmp.GetBitmap(&bi);
       dc.BitBlt(xPos, yPos, bi.bmWidth, bi.bmHeight, &bmDC, 0, 0, SRCCOPY);

I have found out that I should have the following two lines added in after the last line above:

       bmDC.SelectObject(pOldbmp);
       bmDC.DeleteDC();

I want to understand the effect of not having the above two lines.  For example, some users may not use the dialog that this code in in often and others may use it more.  So far I cannot reproduce the 'freezing' defect.

Is there a way I can debug the above code and see the effecs of any GDI leak over time.  What variables should I be looking at?  SHould I monitor 'private bytes' etc??
0
Wanting2LearnMan
Asked:
Wanting2LearnMan
  • 4
  • 3
  • 2
  • +1
7 Solutions
 
Kyle AbrahamsSenior .Net DeveloperCommented:
The effect of the 2 lines is that you're loading the file into memory, and then keeping it locked.  By not calling those lines, you're essentially saying "I'm still using this section of memory."  If possible I would monitor total used memory.  

It's not so much a GDI leak as it is a memory leak.  (Google on memory leaks and you'll get some detailed info.)

You said that it freezes only after several hours of use . . . if the above were the case you can keep calling the above code and make it crash faster.  I'm not sure if MFC has it's own garbage collection, but I doubt it.



0
 
AndyAinscowFreelance programmer / ConsultantCommented:
I think it is in reality a resource HANDLE leak.  The system has only a fixed number of HANDLES (eg. 8192 - this isn't the correct value, just for example).  So as you do not release the bitmap each time you call the routine the handles in use will increase 1, 2, 3... 8191 and then 8192 and then BOOM!  or rather FREEZE! and wierd drawing behaviour.

I once coded a small app to monitor the usage on Windows 3.11 but I have forgotton exactly what function I used :-(

(ps. Might have changed since then. )
0
 
Wanting2LearnManAuthor Commented:
>>So as you do not release the bitmap each time
Do I need to do:
bmp.DeleteObject(); as well or are the below two lines enough

bmDC.SelectObject(pOldbmp);
bmDC.DeleteDC();

Thanks
0
Cloud Class® Course: Ruby Fundamentals

This course will introduce you to Ruby, as well as teach you about classes, methods, variables, data structures, loops, enumerable methods, and finishing touches.

 
AndyAinscowFreelance programmer / ConsultantCommented:
The DeleteDC is not necessary - done for you in the CDC destructior.
0
 
pgnatyukCommented:
Better to delete the DC when the "old bitmap" is selected there.
Why you need to load the bitmap each time when drawing? This bitmap is small enough?
So you need to delete it also or hope that a destructor will do it for you.
CreateCompatibleDC is also a question, if your app should work fast and does not freeze. You can make it once and keep.
0
 
pgnatyukCommented:
Few things to add:
1. The same code can be compiled for Win32, so you can use BoundChecker to detect the errors. Microsoft has tools to detect erros on the device, but... it is not very easy to use. I don't know how you only with debugging your code may detect the GDI/memory problems. Maybe you can detect the fact that you have a leak, but, probably, not the place. So have your code compiled for Win32 and use BoundChecker.
2. Can you say if your control is derived from CWnd, CDialog, etc.? You don't use CPaintDC and I don't understand who validates the invalidated regions on your window.
0
 
Wanting2LearnManAuthor Commented:
>>Why you need to load the bitmap each time when drawing? This bitmap is small enough?
It is a real small bitmap.  I could try only loading it once to see if it makes any difference.

>>So have your code compiled for Win32 and use BoundChecker.
OK I'll try that also.

>>Can you say if your control is derived from CWnd, CDialog, etc.?
It is derived from CDialog.


Thanks for all the help.

0
 
pgnatyukCommented:
So I'm afraid you have to call CDialog:OnPaint too. Otherwise you will have bad problems with the screen validating. And you have to use CPaintDC instead of your CClientDC
0
 
Wanting2LearnManAuthor Commented:
>>Otherwise you will have bad problems with the screen validating
What do you mean by this?

Thanks
0
 
pgnatyukCommented:
From my understanding it has to be something like that:
void CMyDlg::OnPaint()
{
    CPaintDC dc(this);
    CDialog::OnPaint();
     dc.BitBlt(xPos, yPos, m_nWidth, m_nHeight, &m_memDC, 0, 0, SRCCOPY);
}

all other stuff (bitmap loading, size detection, creating the memory DC, etc.) should be in OnInitDialog(), and object destroying (delete memory DC, delete the bitmap) should be in OnDestroy().
for example:
BOOL CMyDlg::OnInitDialog()
{
  CDialog::OnInitDialog();
  m_Bmp.LoadBitmap(IDB_MYBITMAP);
 //other:
//Create DC, SelectObject in this DC, etc.
}
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Cloud Class® Course: Microsoft Office 2010

This course will introduce you to the interfaces and features of Microsoft Office 2010 Word, Excel, PowerPoint, Outlook, and Access. You will learn about the features that are shared between all products in the Office suite, as well as the new features that are product specific.

  • 4
  • 3
  • 2
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now