?
Solved

GDI leak question.

Posted on 2009-05-08
10
Medium Priority
?
509 Views
Last Modified: 2013-12-27
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
Comment
Question by:Wanting2LearnMan
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
  • 3
  • 2
  • +1
10 Comments
 
LVL 40

Assisted Solution

by:Kyle Abrahams
Kyle Abrahams earned 200 total points
ID: 24335446
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
 
LVL 44

Assisted Solution

by:AndyAinscow
AndyAinscow earned 400 total points
ID: 24342657
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
 

Author Comment

by:Wanting2LearnMan
ID: 24343031
>>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
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 44

Assisted Solution

by:AndyAinscow
AndyAinscow earned 400 total points
ID: 24344356
The DeleteDC is not necessary - done for you in the CDC destructior.
0
 
LVL 33

Assisted Solution

by:pgnatyuk
pgnatyuk earned 1400 total points
ID: 24346865
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
 
LVL 33

Assisted Solution

by:pgnatyuk
pgnatyuk earned 1400 total points
ID: 24347172
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
 

Author Comment

by:Wanting2LearnMan
ID: 24352402
>>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
 
LVL 33

Assisted Solution

by:pgnatyuk
pgnatyuk earned 1400 total points
ID: 24352498
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
 

Author Comment

by:Wanting2LearnMan
ID: 24352573
>>Otherwise you will have bad problems with the screen validating
What do you mean by this?

Thanks
0
 
LVL 33

Accepted Solution

by:
pgnatyuk earned 1400 total points
ID: 24353290
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

Featured Post

Get proactive database performance tuning online

At Percona’s web store you can order full Percona Database Performance Audit in minutes. Find out the health of your database, and how to improve it. Pay online with a credit card. Improve your database performance now!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

In this article we will discuss all things related to StageFright bug, the most vulnerable bug of android devices.
Once again I push the limits of my phone.  An introduction to the Android Google Now Launcher.
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.
Suggested Courses
Course of the Month12 days, 2 hours left to enroll

752 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question