线程中TBitmap释放问题

Xhunter 2012-10-26 08:49:38
有个项目要在后台处理图片。一直不放心用GDI+处理,因为要在线程中处理。

为了项目平稳,我单独拿TBitmap来循环20000次测试

//同步线程
for(...)
{
Graphics::TBitmap * bit=new Graphics::TBitmap();

//简单的操作略过
//bit->FreeImage();
::DeleteDC(bit->Canvas->Handle);//这里返回来的是1,表示是成功的
bit->Free();
}

可发现内存会一点点的涨起来,或是虚拟内存,反正是这二者。有时运行2小时后,内存好象没有涨,但出错了“存储空间不足,无法处理命令”

到底TBitmap的释放机制是怎么样的。

...全文
254 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
Xhunter 2012-10-30
  • 打赏
  • 举报
回复
本着有泄漏肯定是自己代码有问题的原则,经过几天的折磨,一段代码一段代码跟踪测试。
最终确定几个重要函数并不象网上说的那样有泄漏。有泄露肯定是用时前后顺序不对。

TBitmap->Assign()
TBitmap->Canvas->StretchDraw()
TJPEGImage->Compress()
TJPEGImage->Assign()

以上函数都没有问题,有泄露肯定是用时前后顺序不对。


线程开始
while(ThEnd)
{
Graphics::TBitmap *getimg=new Graphics::TBitmap();
getimg->HandleType=bmDIB;
getimg->PixelFormat=pf24bit;
getimg->Width=(动态变量);
getimg->Height=bottom(动态变量);
TJPEGImage *AsBit=new TJPEGImage();
AsBit->PixelFormat=jf24Bit;//显式指定

try{
getimg->Canvas->Lock();

....各种画 包括 使用 TJPEGImage
TJPEGImage *DBDwImg=new TJPEGImage(); //记着删除
try{
TJPEGImage *DBDwImg=new TJPEGImage();
//这里应该有try{}catch(...){} 之类 看代码需要
//或从流 DBDwImg->LoadFromStream(...);
//或从文件 DBDwImg->LoadFromFile(...);
getimg->Canvas->StretchDraw(rect,DBDwImg);
}
__finally
{
delete DBDwImg;
}
....各种画 包括 使用 TJPEGImage

try{AsBit->Assign(getimg);}catch(...){....} //转换成JPG
}
__finally
{
getimg->Canvas->Unlock();
delete getimg;
//上面有异常在这里退出并清理场景
if(...){....return;}
}

//最终
try{
...Enter();//申请临界区保护

AsBit->CompressionQuality=...;//压缩比例
AsBit->Compress();
AsBit->SaveToStream(...);//保存到流或文件
}
__finally
{
Leave(); //解锁临界区
delete AsBit
}
}


以上代码在线程中测试了24小时过了,内存包括各种句柄资源 都没有再递增

有些属性和方法有使用顺序的要求。我的日你球的。
ccrun.com 2012-10-27
  • 打赏
  • 举报
回复
对于C++Builder中的VCL对象来说,创建的时候用new,释放的时候建议用delete操作。Free方法只是为了兼容Delphi而存在。所以,将 bit->Free(); 改成 delete bit 再试。另外,DeleteDC这一句,你代码中可有GetDC?这个要配套使用。
Xhunter 2012-10-27
  • 打赏
  • 举报
回复
__finally
{
bit->Canvas->Unlock();
bit->FreeImage();
bit->Height=0;
bit->Width=0;
delete asjpg; //有这一句
}


Xhunter 2012-10-27
  • 打赏
  • 举报
回复
老天啊! 还是不行
我换在外部引用的方式。
全局变量
bit=new Graphics::TBitmap();
bit->PixelFormat=pf24bit; //显式指定DIB
TJPEGImage*jpgimg=new TJPEGImage();

线程同步后
for(...)
{
jpgimg->LoadFromStream(ms); ms是不固定的,很多不同尺寸的JPG图片
TJPEGImage *asjpg=new TJPEGImage();
try{
bit->Height=动态变量; 在2350下滑动
bit->Width=动态变量; 在2350下滑动
}
catch(...){info="申请DIB资源失败";return;}
try{
bit->Canvas->Lock();
...在Canvas中简单的画
...StretchDraw(TRect(0,0,bit->Width,bit->Height),jpgimg);
asjpg->Assign(bit);
asjpg->CompressionQuality=comp;//压缩比例
asjpg->JPEGNeeded();
asjpg->Compress();
asjpg->SaveToStream(jpgms);//保存到指定的流中
}
__finally
{
bit->Canvas->Unlock();
bit->FreeImage();
bit->Height=0;
bit->Width=0;
}
}

//程序关闭时再
delete bit;
delete jpgimg;

运行1-2小时后,就报错了前面那个异常“申请DIB资源失败“

快疯了



Xhunter 2012-10-27
  • 打赏
  • 举报
回复
来人啊
ccrun.com 2012-10-27
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 的回复:]
貌似TBitmap 指定了高和宽后....它就会创建DC..我用::DeleteDC跟踪是返回来的1
[/Quote]

我的建议是:如果你没有显式的调用CreateDC或GetDC,就不要显式的调用DeleteDC。
让TBitmap对象自己去维护这个DC。
Xhunter 2012-10-27
  • 打赏
  • 举报
回复
貌似TBitmap 指定了高和宽后....它就会创建DC..我用::DeleteDC跟踪是返回来的1
Xhunter 2012-10-27
  • 打赏
  • 举报
回复
好的,谢谢!我换delete测试看看
Xhunter 2012-10-26
  • 打赏
  • 举报
回复
//同步线程
for(...)
{
Graphics::TBitmap * bit=new Graphics::TBitmap();
try{
bit->Canvas->Lock();
...在Canvas中简单的画
}
__finally
{
bit->Canvas->Unlock();
}
//bit->FreeImage();
::DeleteDC(bit->Canvas->Handle);//这里返回来的是1,表示是成功的
bit->Free();
}

我用了Lock和Unlock的, 还是出现那些问题

LinuxCard 2012-10-26
  • 打赏
  • 举报
回复
Canvas->Lock()和Canvas->Unlock()
LinuxCard 2012-10-26
  • 打赏
  • 举报
回复
貌似要LOck一下,我似乎有这个印象

13,825

社区成员

发帖
与我相关
我的任务
社区描述
C++ Builder相关内容讨论区
社区管理员
  • 基础类社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧