loadBitmap 资源释放问题

时间:2021-03-14 05:02:24
平台:
 windows ce
 EVC (MFC)

代码:
  CBitmap bmp;
  bmp.LoadBitmap(IDB_BITMAP_A);

  ... ...
   bmp.DeleteObject()
  bmp.LoadBitmap(IDB_BITMAP_B);
  ......
问题:
   在用CBitmap bmp 对象来加载第二张图(IDB_BITMAP_B)的时候,必须先bmp.DeleteObject(),如果不加的话,在debug模式下会出错,出错的地方是:
   

BOOL CGdiObject::Attach(HGDIOBJ hObject)
{
ASSERT(m_hObject == NULL);      // only attach once, detach on destroy
if (hObject == NULL)
return FALSE;
CHandleMap* pMap = afxMapHGDIOBJ(TRUE); // create map if not exist
ASSERT(pMap != NULL);
pMap->SetPermanent(m_hObject = hObject, this);
return TRUE;
}


     起初以为是内存操作的原因要将bmp delete,后来看msdn:

If the bitmap identified by lpszResourceName does not exist or if there is insufficient memory to load the bitmap, the function returns zero.

You can use the CGdiObject::DeleteObject function to delete a bitmap loaded by the LoadBitmap function, or the CBitmap destructor deletes the object for you. 

Before you delete the object, make sure it is not selected into a device context.

The following bitmaps are added to Windows versions 3.1 and later: 

OBM_UPARRROWI 
OBM_DNARROWI 
OBM_RGARROWI 
OBM_LFARROWI 
These bitmaps are not found in device drivers for Windows versions 3.0 and earlier.

In Windows CE, when you use the CBitmap::LoadBitmap method to initialize a CBitmap object, the bitmap is read-only.  This is because Windows CE does not copy the bitmap into RAM, as the Windows-based desktop platforms do. In Windows CE, the bitmap only exists in a resource, which is part of the executable file of the program. When you select the bitmap into a device context, you cannot modify the device context—for example, by drawing text into it—because that would require the ability to write to the bitmap.

Windows CE does not support any predefined bitmaps, so you cannot use any OBM_* values in the lpszResourceName parameter.

Because Windows CE 1.0 only supports a 2 bit gray scale palette, use bitmaps that are one bit per pixel (monochrome .bmp) or two bits per pixel (.2bpp).


问题一
说明位图并不会加载到ram里面去的,是这样吗?
如果不是,就如msdn所说是exe模块的资源部分部分,
BOOL CGdiObject::Attach(HGDIOBJ hObject) 代码里面就是在做这种映射吧?

CHandleMap* pMap = afxMapHGDIOBJ(TRUE); // create map if not exist
必须是not exist才可以创建!


问题二:
如果不deleteobject(),在release 模式下,程序照样可以运行,界面显示不会受影响,但在debug模式下就会报错, 必须先delete才可以!  怎么解释?  如果不delete,程序运行会出现怎么样的异常? 或者说对软件的健壮性有怎样的影响?


     





   

7 个解决方案

#1


CBitmap bmp;
   bmp.LoadBitmap(IDB_BITMAP_A);

  ... ...
   bmp.DeleteObject()
   bmp.LoadBitmap(IDB_BITMAP_B);一个对象关联两个资源,你在关联下一个资源的时候,就必须释放掉第一个关联的资源,否则就错误。

#2


WinCE平台有些表现和PC不一样,可能在WinCE不会显示异常对话框窗口,而在PC上则显示。。
做WinCE平台遇到过很多这样的问题。。。

#3


因为debug下会进行一些初始化和检查工作。当重指向资源时,DEBUG就建议你先删除原有资源;RELEASE不会做这些工作,一切后果自负,因此有时是可以通过的,但也许会出现资源的泄漏。

#4


In Windows CE, when you use the CBitmap::LoadBitmap method to initialize a CBitmap object, the bitmap is read-only.  This is because Windows CE does not copy the bitmap into RAM, as the Windows-based desktop platforms do. In Windows CE, the bitmap only exists in a resource, which is part of the executable file of the program. When you select the bitmap into a device context, you cannot modify the device context—for example, by drawing text into it—because that would require the ability to write to the bitmap.

既然bitmap不会加载到内存,会出现内存泄露吗?   
可我记得在pc上loadimage的时候,内存使用是会上升的啊 !

应该是exe执行的时候就不开辟一段内存用于存放资源的吧?只不过是每次加载资源位图的时候,只是做一个映射,而不是重新加载到内存。是这样的吗?

#5


引用 3 楼 happyparrot 的回复:
因为debug下会进行一些初始化和检查工作。当重指向资源时,DEBUG就建议你先删除原有资源;RELEASE不会做这些工作,一切后果自负,因此有时是可以通过的,但也许会出现资源的泄漏。

up

#6


引用 4 楼 trueman_onlyme 的回复:
既然bitmap不会加载到内存,会出现内存泄露吗?   
可我记得在pc上loadimage的时候,内存使用是会上升的啊 !

应该是exe执行的时候就不开辟一段内存用于存放资源的吧?只不过是每次加载资源位图的时候,只是做一个映射,而不是重新加载到内存。是这样的吗?


的确是先开辟一段内存用于存放资源的,IDB_BITMAP_A、IDB_BITMAP_B在编译的时候已经确定使用空间。

加载到内存是资源自己的数据,下面的语很明白了:
If the bitmap identified by lpszResourceName does not exist or if there is insufficient memory to load the bitmap, the function returns zero.

按理要重新加载的。

#7


您好
我是本版版主
此帖已多日无人关注
请您及时结帖
如您认为问题没有解决可按无满意结帖处理
另外本版设置了 疑难问题汇总帖
并已在版面置顶
相关规定其帖子中有说明
您可以根据规定提交您帖子的链接
如您目前不想结帖只需回帖说明
我们会删除此结帖通知

见此回复三日内无回应
我们将强制结帖
相关规定详见界面 界面版关于版主结帖工作的具体办法

#1


CBitmap bmp;
   bmp.LoadBitmap(IDB_BITMAP_A);

  ... ...
   bmp.DeleteObject()
   bmp.LoadBitmap(IDB_BITMAP_B);一个对象关联两个资源,你在关联下一个资源的时候,就必须释放掉第一个关联的资源,否则就错误。

#2


WinCE平台有些表现和PC不一样,可能在WinCE不会显示异常对话框窗口,而在PC上则显示。。
做WinCE平台遇到过很多这样的问题。。。

#3


因为debug下会进行一些初始化和检查工作。当重指向资源时,DEBUG就建议你先删除原有资源;RELEASE不会做这些工作,一切后果自负,因此有时是可以通过的,但也许会出现资源的泄漏。

#4


In Windows CE, when you use the CBitmap::LoadBitmap method to initialize a CBitmap object, the bitmap is read-only.  This is because Windows CE does not copy the bitmap into RAM, as the Windows-based desktop platforms do. In Windows CE, the bitmap only exists in a resource, which is part of the executable file of the program. When you select the bitmap into a device context, you cannot modify the device context—for example, by drawing text into it—because that would require the ability to write to the bitmap.

既然bitmap不会加载到内存,会出现内存泄露吗?   
可我记得在pc上loadimage的时候,内存使用是会上升的啊 !

应该是exe执行的时候就不开辟一段内存用于存放资源的吧?只不过是每次加载资源位图的时候,只是做一个映射,而不是重新加载到内存。是这样的吗?

#5


引用 3 楼 happyparrot 的回复:
因为debug下会进行一些初始化和检查工作。当重指向资源时,DEBUG就建议你先删除原有资源;RELEASE不会做这些工作,一切后果自负,因此有时是可以通过的,但也许会出现资源的泄漏。

up

#6


引用 4 楼 trueman_onlyme 的回复:
既然bitmap不会加载到内存,会出现内存泄露吗?   
可我记得在pc上loadimage的时候,内存使用是会上升的啊 !

应该是exe执行的时候就不开辟一段内存用于存放资源的吧?只不过是每次加载资源位图的时候,只是做一个映射,而不是重新加载到内存。是这样的吗?


的确是先开辟一段内存用于存放资源的,IDB_BITMAP_A、IDB_BITMAP_B在编译的时候已经确定使用空间。

加载到内存是资源自己的数据,下面的语很明白了:
If the bitmap identified by lpszResourceName does not exist or if there is insufficient memory to load the bitmap, the function returns zero.

按理要重新加载的。

#7


您好
我是本版版主
此帖已多日无人关注
请您及时结帖
如您认为问题没有解决可按无满意结帖处理
另外本版设置了 疑难问题汇总帖
并已在版面置顶
相关规定其帖子中有说明
您可以根据规定提交您帖子的链接
如您目前不想结帖只需回帖说明
我们会删除此结帖通知

见此回复三日内无回应
我们将强制结帖
相关规定详见界面 界面版关于版主结帖工作的具体办法