Solved

GDI leak question.

Posted on 2009-05-08
10
475 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
  • 4
  • 3
  • 2
  • +1
10 Comments
 
LVL 40

Assisted Solution

by:Kyle Abrahams
Kyle Abrahams earned 50 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 100 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
Announcing the Most Valuable Experts of 2016

MVEs are more concerned with the satisfaction of those they help than with the considerable points they can earn. They are the types of people you feel privileged to call colleagues. Join us in honoring this amazing group of Experts.

 
LVL 44

Assisted Solution

by:AndyAinscow
AndyAinscow earned 100 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 350 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 350 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 350 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 350 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

Live: Real-Time Solutions, Start Here

Receive instant 1:1 support from technology experts, using our real-time conversation and whiteboard interface. Your first 5 minutes are always free.

Question has a verified solution.

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

Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
Exception Handling is in the core of any application that is able to dignify its name. In this article, I'll guide you through the process of writing a DRY (Don't Repeat Yourself) Exception Handling mechanism, using Aspect Oriented Programming.
The goal of the tutorial is to teach the user how to use functions in C++. The video will cover how to define functions, how to call functions and how to create functions prototypes. Microsoft Visual C++ 2010 Express will be used as a text editor an…
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.

813 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

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now