Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

help! running out of GDI resources

101 views
Skip to first unread message

Lee Perkins

unread,
May 1, 1998, 3:00:00 AM5/1/98
to

When you select a GDI object into your DC (I'm not familiar with MFC, so I
don't know if MFC buffers you from this task), do you save the object you
just replaced and select it back into the DC before your function goes out
of scope?

Frank Paynter wrote in message <01bd749f$b2fd2ac0$0202a8c0@frank>...
>I recently noted (when my development system crashed yet again) that my app
>seems to have developed a fondness for GDI resources, consuming them at a
>great rate until they are completely exhausted or my system locks up,
>whichever comes first. Looking back at previous versions, I see they all
>exhibit the same behavior, except now my wireframe models are complex
>enough so that resource consumption has become a real issue. In a recent
>experiment, I got the following results:
>
>0. Note System/User/GDI resources remaining (58/58/70)
>1. Open app -- resources go to 55/55/70
>2. Open Document (CEnhancedEdit)-- resources go to 55/55/69
>3. Open View (draws a wireframe model of an airplane) -- resources stay
>55/55/69
>4. Force wireframe view redraws by rotating aircraft model -- GDI resources
>start dropping rapidly
>5. Stop forcing redraws & wait for many seconds for OnIdle to run & recover
>resources -- doesn't happen
>6. Dismiss wireframe view -- resources do not recover
>7. Dismiss document view -- resources do not recover
>8. Quit app -- resources recover to 57/57/70
>
>To the best of my knowledge, all my drawing code is on the stack; I do not
>create any pens or GDI objects with 'new'. According to my readings in the
>help files, Petzhold, etc, GDI objects created on the stack should be
>recovered the next time CWinApp::OnIdle() runs after the OnDraw routine
>completes (i.e., the GDI objects go out of scope).
>
>I have not overridden CWinApp::OnIdle(), although I am considering doing
>this just so I can see whether or not it ever runs.
>
>Anyone have any ideas about what I'm doing wrong here, or troubleshooting
>ideas? I've combed the MSKB, CodeGuru, etc, w/o much luck.
>
>TIA,
>
>Frank
>

Cameron Murray

unread,
May 1, 1998, 3:00:00 AM5/1/98
to

I hope you are deleting the GDI objects you create and use during
OnDraw() or OnPaint()...

For example:

OnDraw()
{
CBrush brush;
brush.CreateSolidBrush( color );
}

This is bad news as the brush object has not been deleted...this is
better:

OnDraw()
{
CBrush brush;
brush.CreateSolidBrush( color );

..use..

brush.DeleteObject();
}

Similarly :

OnDraw()
{
CDC tempDC;
tempDC.CreateCompatibleDC( NULL );
}

Bad news again...you need to do this :

OnDraw()
{
CDC tempDC;
tempDC.CreateCompatibleDC( NULL );

..use..

tempDC.DeleteDC();
}

Also remember to select any objects out of the device context before
destroying them.

If you are already doing all this then who knows!

Dirk Djuga

unread,
May 1, 1998, 3:00:00 AM5/1/98
to


There are 2 "sins" that would eat ressources with MFC:

whenever you select an object into a DC you must keep the previous object
and re-select it into the dc

CPen* pOldPen=pDC->SelectObject(&Pen);
...
pDC->SelectObject(pOldPen);

and before you create a new GDI object you must detach (and delete) the old
one eg. CGDIObject::DeleteObject(), or better yet always construct a fresh
MFC object.

CPen* pPen;
pPen=new CPen;
pPen->CreatePen(....
...
delete pPen;
pPen=new CPen;
pPen->CreatePen(...

instead of just

CPen Pen;
Pen.CreatePen(...
Pen.CreatePen(... //no-no

It's true that GDI Objects are deleted by the MFC classes, so that you
normally need not call DeleteObject() or DeleteDC() *except* when you reuse
the MFC CGDIObject object.

cU
--
Dirk Djuga mailto:di...@solaris.stuttgart.netsurf.de
http://djuga.home.ml.org
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*NEW*: Retriever 1.1 is out: http://retriever.home.ml.org

Shareware image viewer, thumbnailer & database
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


jeff denson

unread,
May 1, 1998, 3:00:00 AM5/1/98
to

Not true, the CBrush destructor will attempt to delete the object
However, this will fail if the object is selected into a HDC
Since there is no VERIFY or ASSERT on the DeleteObject()
(shame on MS programmers) you will not get any notification
when this happens
This is a common source of leaks

example


{
CBrush brush;
brush.CreateSolidBrush( color );

CDC dc;
dc.CreateCompatibleDC( NULL );

dc.SelectObject( &brush );
}

no leak, since the CDC destructor de-selects the brush
and the CBrush destructor deletes the brush
however this leaks
{
CDC dc;
dc.CreateCompatibleDC( NULL );

CBrush brush;
brush.CreateSolidBrush( color );

dc.SelectObject( &brush );
}

because the CBrush destructor is called while
the brush is still selected into the CDC
therefore the DeleteObject will fail

Frank Paynter

unread,
May 2, 1998, 3:00:00 AM5/2/98
to


Dirk,


> There are 2 "sins" that would eat ressources with MFC:
>
> whenever you select an object into a DC you must keep the previous object
> and re-select it into the dc
>
> CPen* pOldPen=pDC->SelectObject(&Pen);
> ...
> pDC->SelectObject(pOldPen);

OK, I'm doing that.

>
> and before you create a new GDI object you must detach (and delete) the
old
> one eg. CGDIObject::DeleteObject(), or better yet always construct a
fresh
> MFC object.
>
> CPen* pPen;
> pPen=new CPen;
> pPen->CreatePen(....
> ...
> delete pPen;
> pPen=new CPen;
> pPen->CreatePen(...
>
> instead of just
>
> CPen Pen;
> Pen.CreatePen(...
> Pen.CreatePen(... //no-no
>
> It's true that GDI Objects are deleted by the MFC classes, so that you
> normally need not call DeleteObject() or DeleteDC() *except* when you
reuse
> the MFC CGDIObject object.

OOPS! This may be what is happening. I create *several* pens of different
colors, and then use them as required during the draw routine. Although I
am careful to reselect the original pen back into the DC before exiting
OnDraw, I *do not* explicitely delete any of the pens I created. All the
documentation says that any GDI objects created on the local stack get
deleted by MFC on exit. Don't tell me that MickeySoft lied to me again
<g>!??

I'll definitely check this out tomorrow (too late tonight -neurons all went
to sleep some time ago :) )

Frank


Frank Paynter

unread,
May 2, 1998, 3:00:00 AM5/2/98
to

Cameron,

Cameron Murray <aim...@aimdata.com.au> wrote in article
<354A67...@aimdata.com.au>...


> I hope you are deleting the GDI objects you create and use during
> OnDraw() or OnPaint()...

No, I'm *not* deleting them. The documentation explicitely says you don't
have to delete GDI objects unless you have created them using NEW.
However, it wouldn't be the first time I've misinterpreted what Mickeysoft
is telling me <sigh>. I will check it out tomorrow.

Frank


>
> For example:


>
> OnDraw()
> {
> CBrush brush;
> brush.CreateSolidBrush( color );
> }
>
> This is bad news as the brush object has not been deleted...this is
> better:
>
> OnDraw()
> {
> CBrush brush;
> brush.CreateSolidBrush( color );
>
> ..use..
>
> brush.DeleteObject();
> }
>

Jeremy Lloyd

unread,
May 3, 1998, 3:00:00 AM5/3/98
to

Can I interject here?

You DO NOT need to delete you resources before your handler quits. The
destructor will do this for you. See CGdiObject::~CGdiObject() in
AfxWin1.INL (...\vc\mfc\include).

Further, if you do attempt to attach a new resource to an existing
object that's holding a resource (as suggested), an assertion will be
raised, if you're running a Debug build. See CGdiObject::Attach in
WinGdi.CPP (...\vc\mfc\src).

You definitely do need, as suggested, to select resources out of the DC.

So... I guess there's something else wrong.

Regards
Jeremy

0 new messages