首页
社区
课程
招聘
[求助]感觉这个函数会内存泄漏,谁能找出在哪里?
发表于: 2012-4-10 21:21 5378

[求助]感觉这个函数会内存泄漏,谁能找出在哪里?

2012-4-10 21:21
5378
void CTestDlg::SaveScreen(CString &path)
{
        HBITMAP   hBmp;
        HDC     hDC, MemDC,hDCC; //设备描述表      
        BYTE*   Data;        
    BITMAPINFO   bi;   

    int            iBits;//当前显示分辨率下每个像素所占字节数   
WORD           wBitCount;//位图中每个像素所占字节数      
DWORD          dwPaletteSize=0;//定义调色板大小   
DWORD          dwBmBitsSize;//位图中像素字节大小   
DWORD          dwDIBSize;// 位图文件大小   
DWORD          dwWritten;//写入文件字节数   
BITMAP         Bitmap;//位图结构   
BITMAPFILEHEADER   bmfHdr;   //位图属性结构      
BITMAPINFOHEADER   bih;       //位图文件头结构   
LPBITMAPINFOHEADER lpbi;     //位图信息头结构  指向位图信息头结构   
HANDLE          fh;//定义文件句柄   
HANDLE   hDib;//分配内存句柄   
HANDLE   hPal;//分配内存句柄   
HANDLE          hOldPal=NULL;//调色板句柄

CString lpFileName=path;

memset(&bi,   0,   sizeof(bi));         
bi.bmiHeader.biSize   =   sizeof(BITMAPINFO);      
bi.bmiHeader.biWidth   =  GetSystemMetrics(SM_CXSCREEN);         
bi.bmiHeader.biHeight   = GetSystemMetrics(SM_CYSCREEN);         
bi.bmiHeader.biPlanes   =   1;         
bi.bmiHeader.biBitCount   =   24;               
hDC   =   ::GetDC(NULL);      //获取屏幕DC   
MemDC   =   CreateCompatibleDC(hDC);    //     建立内存DC
hBmp   =   CreateDIBSection(MemDC,   &bi, DIB_RGB_COLORS,   (void**)&Data,   NULL,   0);         
SelectObject(MemDC,   hBmp);         
BitBlt(MemDC,   0,   0,   bi.bmiHeader.biWidth,   bi.bmiHeader.biHeight,hDC,   0,   0,   SRCCOPY);         
::ReleaseDC(NULL,   hDC);        
DeleteDC(MemDC);   
    /************************************************************************/
   
    //计算位图文件每个像素所占字节数   
hDCC = CreateDC("DISPLAY",NULL,NULL,NULL);   
iBits = GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES);   
DeleteDC(hDCC);

   /* if (iBits  <= 1)      
  wBitCount = 1;   
else if (iBits  <= 4)      
  wBitCount = 4;   
else if (iBits  <= 8)      
  wBitCount = 8;   
else if (iBits  <= 24)   
  wBitCount = 24;   
else if (iBits <=32)   
  wBitCount = 24;
    */
wBitCount=32;
//计算调色板大小   
if (wBitCount  <= 8)      
  dwPaletteSize = (1  << wBitCount) *sizeof(RGBQUAD);

//设置位图信息头结构   
GetObject(hBmp, sizeof(BITMAP), (LPSTR)&Bitmap);   
bih.biSize            = sizeof(BITMAPINFOHEADER);   
bih.biWidth           = Bitmap.bmWidth;   
bih.biHeight          = Bitmap.bmHeight;   
bih.biPlanes          = 1;   
bih.biBitCount         = wBitCount;     
bih.biCompression      = BI_RGB;   
bih.biSizeImage        = 0;   
bih.biXPelsPerMeter     = 0;   
bih.biYPelsPerMeter     = 0;   
bih.biClrUsed         = 0;   
bih.biClrImportant      = 0;   
dwBmBitsSize = ((Bitmap.bmWidth *wBitCount+31)/32)* 4*Bitmap.bmHeight ;

//为位图内容分配内存   
hDib  = GlobalAlloc(GHND,dwBmBitsSize+dwPaletteSize+sizeof(BITMAPINFOHEADER));   
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib);   
if (lpbi==NULL)   
{   
         GlobalUnlock(hDib);   
GlobalFree(hDib);  
delete Data;
  return ;   
}
*lpbi = bih;    // 处理调色板   
hPal = GetStockObject(DEFAULT_PALETTE);

if (hPal)  
{      
         hDCC  = ::GetDC(NULL);      
  hOldPal = ::SelectPalette(hDCC, (HPALETTE)hPal, FALSE);      
  RealizePalette(hDCC);     
}

    // 获取该调色板下新的像素值   
GetDIBits(hDCC, hBmp, 0, (UINT) Bitmap.bmHeight,      
  (LPSTR)lpbi + sizeof(BITMAPINFOHEADER)+dwPaletteSize,   
  (LPBITMAPINFO)lpbi, DIB_RGB_COLORS);

    //恢复调色板      
if (hOldPal)     
{      
  SelectPalette(hDCC, (HPALETTE)hOldPal, TRUE);      
  RealizePalette(hDCC);      
  ::ReleaseDC(NULL, hDCC);   
}

//创建位图文件        
fh = CreateFile(lpFileName.GetBuffer(NULL), GENERIC_WRITE,      
  0, NULL, CREATE_ALWAYS,      FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);      
if (fh == INVALID_HANDLE_VALUE)      
  return ;

    // 设置位图文件头   
bmfHdr.bfType = 0x4D42;  // "BM"   
dwDIBSize    = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)+ dwPaletteSize + dwBmBitsSize;      
bmfHdr.bfSize = dwDIBSize;   
bmfHdr.bfReserved1 = 0;   
bmfHdr.bfReserved2 = 0;   
bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER)+ dwPaletteSize;
   
// 写入位图文件头   
WriteFile(fh, (LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER), &dwWritten, NULL);      
// 写入位图文件其余内容   
WriteFile(fh, (LPSTR)lpbi, dwDIBSize, &dwWritten, NULL);

//清除      
GlobalUnlock(hDib);   
GlobalFree(hDib);   
CloseHandle(fh);  
delete Data;
delete &bi;
return;
}

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (5)
雪    币: 128
活跃值: (27)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
2
一堆
if (false)
{
    delete o1;
    return;
}
if (false)
{
    delete o1;
    delete o2;
    return;
}
越往后越悲剧

我最不喜欢这种写法……

我喜欢这样
do
{
    if (false) break;
    ...
    if (false) break;

}while(FALSE);

if (o1) delete o1;
if (o2) delete o2;
2012-4-10 22:14
0
雪    币: 142
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
太长了不看...
其实只要把配对做好,就能很大几率减少泄漏
2012-4-10 23:30
0
雪    币: 367
活跃值: (20)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
4
hBmp   GDI对象泄漏.

另外,这么长的代码,不如写成一个小类,这样类的析构函数中写回收代码.这样一路下去,只要判断true的情况就行了.
2012-4-19 13:18
0
雪    币: 1708
活跃值: (586)
能力值: ( LV15,RANK:670 )
在线值:
发帖
回帖
粉丝
5
也可以把释放的地方统一放到最后,出错了就跳过去。
2012-4-19 18:25
0
雪    币: 44
活跃值: (25)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
6
2012-4-19 18:54
0
游客
登录 | 注册 方可回帖
返回
//