win2000正常,98里面系统资源泄漏,急!!!!!

ccnuxjg 2002-11-21 06:25:30
此函数在2000和XP下面运行一切正常。但是在WIN98下面就会如下现象:

在OnTimer里面调用此函数(每隔一秒调用一次),大约过几分钟之后,整个系统就会慢起来。首先,图形绘制不出来,然后整个WINDOWS的重绘机制都好像失效。

可是我却找不到有什么资源泄漏的地方。经过反复测试,发现问题不可能发生在别的地方。 烦闹各位大仙帮帮忙!!!!

void DrawGraphyClass::DrawGraphy ( CDC *pDC, const int _InputRate )
{
CDC MemDC;
CBitmap MemBitmap;

MemDC.CreateCompatibleDC ( NULL );
MemBitmap.CreateCompatibleBitmap ( pDC, m_DisplayRect.right - m_DisplayRect.left, m_DisplayRect.bottom - m_DisplayRect.top );

CBitmap *pOldBit=MemDC.SelectObject(&MemBitmap);

MemDC.FillSolidRect (0, 0, m_DisplayRect.right - m_DisplayRect.left, m_DisplayRect.bottom - m_DisplayRect.top, RGB(0, 0, 0));
CPen pen;
CPen *OldPen;
pen.CreatePen(PS_SOLID, 1, m_GridColor );
OldPen=MemDC.SelectObject(&pen);

static int count = 0;

count ++;

int _Interval = m_nInterval / m_nTimes; //ÿÒƶ¯Ò»´ÎµÄ¾àÀë

for ( int i = 1; i <= m_nHorNum; i++ )
{
MemDC.MoveTo ( 0, i * m_nInterval );
MemDC.LineTo ( m_DisplayRect.right - m_DisplayRect.left, i * m_nInterval );
}
for ( int j = 1; j <= m_nColNum; j++ )
{
count = count % m_nTimes;
MemDC.MoveTo ( j * m_nInterval - count * _Interval, 0 );
MemDC.LineTo ( j * m_nInterval - count * _Interval, m_DisplayRect.bottom - m_DisplayRect.top );
}

MemDC.SelectObject(&OldPen);
pen.DeleteObject();

pen.CreatePen (PS_SOLID, 1, m_LineColor );
OldPen = MemDC.SelectObject ( &pen );

float _fTempInterval = static_cast<float> ( m_DisplayRect.bottom - m_DisplayRect.top ) / 100 ;
int _yPos = static_cast<int> ( m_DisplayRect.bottom - m_DisplayRect.top - _InputRate * _fTempInterval + 0.5 );

std::list<CPoint>::iterator it;

if ( m_PointList.size() < m_nTotalNum )
{
m_PointList.push_back ( CPoint ( m_DisplayRect.right - m_DisplayRect.left, _yPos ) );
}
else
{
m_PointList.push_back ( CPoint ( m_DisplayRect.right - m_DisplayRect.left, _yPos ) );
m_PointList.pop_front ();
}
for ( it = m_PointList.end(); it != m_PointList.begin(); it-- )
{
it->x = it->x - _Interval;
}
it->x = it->x - _Interval;
int n=0;
for ( it = m_PointList.end(), n=0, it--; it != m_PointList.begin() && n<= m_PointList.size(); it--, n++ )
{
CPoint _tempPoint = *it;
CPoint _TempPoint = *--it;
it++;
MemDC.MoveTo ( _tempPoint );
MemDC.LineTo ( _TempPoint );
}


pDC->BitBlt ( m_DisplayRect.left, m_DisplayRect.top, m_DisplayRect.right-m_DisplayRect.left, m_DisplayRect.bottom-m_DisplayRect.top, &MemDC, 0, 0, SRCCOPY );

MemDC.SelectObject(&OldPen);
pen.DeleteObject();

MemBitmap.DeleteObject();
MemDC.DeleteDC();

}


实在是不解!
...全文
14 点赞 收藏 34
写回复
34 条回复
beni 2002年11月22日
就是资源错误啊
开始时你有这句:
CBitmap *pOldBit=MemDC.SelectObject(&MemBitmap);
最后要选回来的
在 MemBitmap.DeleteObject();之前加上
MemDC.SelectObject(&pOldBit);

回复 点赞
ccnuxjg 2002年11月22日
To nbgyf(梅花峰):邮件已发,情帮忙看看!
回复 点赞
HuWenjin 2002年11月22日
DrawGraphy ( CDC *pDC, const int _InputRate )

传入的 pDC 查了没有? 其它相关的地方呢?
回复 点赞
termite 2002年11月22日
我遇到过和你一样的问题,后来解决了,自己好好找找吧,多调试,我现在心情不好,等好了再来看这个帖子。
回复 点赞
nbgyf 2002年11月22日
你的For循环正确吗?

正确的话;那就是你的WM_TIMER设置时间要加大,使用GDI是极耗资源的;

再者:

你的MemBitmap变量定义到该类的头文件中,在类析构时释放;
MemDC.SelectObject(&OldPen);
ReleaseDC(&m_MemDC);

现在看看可以吗?

如果还不行,把程序发过来;

俺给您调调,看看可不可以搞定!!!!!!!!!!!!

nbgyf@yeah.net




回复 点赞
nbgyf 2002年11月22日
既然程序结果正确,那就是你的资源释放有问题;

MemDC.SelectObject(&OldPen);
pen.DeleteObject();

MemBitmap.DeleteObject();
MemDC.DeleteDC();

改为:
MemDC.SelectObject(&OldPen);
ReleaseDC(&m_MemDC);
MemBitmap.DeleteObject();
m_MemBitmap.Detach();

请再试试


Good Luck
回复 点赞
ccnuxjg 2002年11月22日
谢谢各位的答复。
我将资源创建放到单个的函数里面,只执行一次,程序结果就正确了。

TO nbgyf(梅花峰):可能你还没有看清楚我的程序。为什么不能那么写呢?MemDC 只不过是内存DC而已。
回复 点赞
wangyexin 2002年11月22日
Create MEM DC -> MemeCompatibleDC ( pDC);
Delete GDI object then detach it -> MemBitmap.DeleteObject();
m_MemBitmap.Detach();
回复 点赞
nbgyf 2002年11月22日
最后一段:
pDC->BitBlt ( m_DisplayRect.left, m_DisplayRect.top, m_DisplayRect.right-m_DisplayRect.left, m_DisplayRect.bottom-m_DisplayRect.top, &MemDC, 0, 0, SRCCOPY );

MemDC.SelectObject(&OldPen);
pen.DeleteObject();

MemBitmap.DeleteObject();
MemDC.DeleteDC();

改为:
MemDC.SelectObject(&OldPen);
ReleaseDC(&m_MemDC);
ReleaseDC(&MemBitmap);

将pDC->BitBlt ( m_DisplayRect.left, m_DisplayRect.top, m_DisplayRect.right-m_DisplayRect.left, m_DisplayRect.bottom-m_DisplayRect.top, &MemDC, 0, 0, SRCCOPY );放到OnPaint()里
回复 点赞
nbgyf 2002年11月22日
看了一下你的绘图程序有问题,怎么能这样写呢!!!!!!!!!
CClientDC dc(this); //添加之

if (m_MemDC.GetSafeHdc() == NULL)//添加之
{
MemDC.CreateCompatibleDC ( &dc);//修改之
MemBitmap.CreateCompatibleBitmap ( pDC, m_DisplayRect.right - m_DisplayRect.left, m_DisplayRect.bottom - m_DisplayRect.top );
...............
}

你再试试,你的循环进的去吗?

回复 点赞
smallz 2002年11月22日
我想,你应该在MemDC.SelectObject(&OldPen);语句前加上这一句就可以了
if( pOldBit )
{
MemDC.SelectObject( pOldBit );
}
这个问题我也遇到,我是这样解决的;
如果还没解决的话,来信,我给你前后两个例子比较。
doublestarts@hotmail.com
回复 点赞
nbgyf 2002年11月22日
是不是绘图发生的异常,可以用For循环测试;

for(int i=0;i<1000;i++)
{
}

如果不出现你的问题就是WM_TIMER的设置有问题,否则就是你的绘图有问题
回复 点赞
ccnuxjg 2002年11月22日
在TRY里面也得不到。

郁闷!!!
回复 点赞
ccnuxjg 2002年11月22日
To cbc(逍遥子) :试过了,绝对不是机器的问题!

To Saimen(单身情人):试验中...


经过了昨天一天一晚的调试和今天一早的调试,我发现程序总是在SelectObject是出现问题,GetLastError()函数也总是返回0。可是我在几个SelectObject后面加ASSERT( pOldBit != NULL),调试就会在该处出现问题,并提示。
为什么运行着好好的,就会出现 pOldBit == NULL 呢!

回复 点赞
sunheart 2002年11月22日
我看了,觉得确实没有泄露,估计是WIN98管理DC的BUG(呵呵)。换这个函数释放DC试试:ReleaseDC(MemDC);我以前也做过类似画图的程序,2000下正常,98下出很怪的结果,当然不是泄露问题。最后我不得不画它两遍才搞定。莫名其妙!
回复 点赞
HuWenjin 2002年11月22日
在 try 中做图
回复 点赞
HuWenjin 2002年11月22日
这样啊,那就试试 try catch 看下面的

TRY
{
// 选择原始图像到图像 dcImage.m_hDC 中
pOldBitmapImage = (HBITMAP*)::SelectObject(dcImage.m_hDC,m_hBitmap);

// 创建掩码位图 bitmapTrans
CBitmap bitmapTrans;
int nWidth = SORect.Width();
int nHeight = SORect.Height();
bitmapTrans.CreateBitmap(nWidth, nHeight, 1, 1, NULL);

// 选择掩码位图 bitmapTrans 到 dcTrans DC中
pOldBitmapTrans = dcTrans.SelectObject(&bitmapTrans);

// 创建掩码图像(基于指定的颜色)
switch(mode)
{
case 0:
case 1:
dcImage.SetBkColor(cTransColor); //删除或保留指定的色
break;
case 2:
default:
dcImage.SetBkColor(m_cBkColor); //显示所有色
break;
}
dcTrans.BitBlt(0, 0, nWidth, nHeight, &dcImage, SORect.left, SORect.top, SRCCOPY);

// 显示透明位图
/* 设置目标DC的拉伸模式为STRETCH_DELETESCANS,也就是不显示拉伸掉的图像 */
srlold = pDC->SetStretchBltMode(STRETCH_DELETESCANS);

// 显示位图
pDC->StretchBlt(DCRect.left,DCRect.top,DCRect.Width(),DCRect.Height(),
&dcImage,SORect.left,SORect.top,SORect.Width(),SORect.Height(),SRCINVERT);
pDC->StretchBlt(DCRect.left,DCRect.top,DCRect.Width(),DCRect.Height(),
&dcTrans,SORect.left,SORect.top,SORect.Width(),SORect.Height(),SRCAND);
pDC->StretchBlt(DCRect.left,DCRect.top,DCRect.Width(),DCRect.Height(),
&dcImage,SORect.left,SORect.top,SORect.Width(),SORect.Height(),SRCINVERT);

// 恢复设备描述表原来的设置
pDC->SetStretchBltMode(srlold);

// 恢复设置
::SelectObject(dcImage.m_hDC,pOldBitmapImage);
dcTrans.SelectObject(pOldBitmapTrans);
pDC->SetBkColor(crOldBack);
pDC->SetTextColor(crOldText);
}
CATCH_ALL(e)
{
处理绘图可能发生的异常

}
END_CATCH_ALL
回复 点赞
cbc 2002年11月22日
换台机子试试
回复 点赞
ccnuxjg 2002年11月22日
To Saimen(单身情人)我作图时只是在旁边呆呆的等着,什么也不干。它也会出问题。

TO zx_sanjin(1.5kg):我也认为是操作系统的问题了. :(
回复 点赞
HuWenjin 2002年11月22日
仔细看了一下代码,发现是没有资源没有释放的情况,那是在做图时,鼠标消息常暂停了 WM_TIMER 消息,多次后出问题吧,

最好不用 WM_TIMER
回复 点赞
发动态
发帖子
VC/MFC
创建于2007-09-28

7893

社区成员

42.1w+

社区内容

VC/MFC相关问题讨论
社区公告
暂无公告