小弟我现在有以下这一段代码,能正常运行,也能得到想要的结果,但是不知道这段代码多次运行是否会造成 
资源泄露,或者有一些隐患在?有请各位有空的高手指点指点? 该函数如下: 
//根据这四个参数的内容来生成BMP格式的数据. 
//生成的图片格式是 258*128,是黑白两色的BMP图 
bool makedisplaybmp(int nThisPrice,int nAcuPrice,int vipScore,CString strVipCode) 

//生成图片 CDC memDC; //主窗体其实是隐藏的,也疑惑这句调用不知道是否合适. 
CWnd *pWnd=AfxGetMainWnd(); 
CDC *pDC=pWnd->GetDC(); CFont fontBlack; 
CString strMsg; 
CBitmap bmpSave; 
BITMAP  bmpInfo; 
LOGFONT lfBlack; 
LOGBRUSH lbBack; //背景色 
CBrush bhBack; 
unsigned short usTmp; 
int nLen,nWidth,nHeight; BITMAPFILEHEADER fileHead; memset(&lfBlack,0,sizeof(lfBlack)); //字体是黑色 
lfBlack.lfHeight =24; 
strcpy(lfBlack.lfFaceName,_T("宋体")); 
lfBlack.lfWeight =FW_BOLD; 
fontBlack.CreateFontIndirect(&lfBlack); lbBack.lbColor =RGB(255,255,255); //背景色是白色 
lbBack.lbStyle =BS_SOLID; 
bhBack.CreateBrushIndirect(&lbBack); bmpSave.CreateBitmap(256,128,1,1,NULL);        //宽度256,高度是128 
memDC.CreateCompatibleDC(pDC); CBitmap *pOldBmp=memDC.SelectObject(&bmpSave); 
CFont *pOldFont=memDC.SelectObject(&fontBlack); 
CBrush *pOldBrush=memDC.SelectObject(&bhBack); CRect rect; 
rect.top =0; 
rect.bottom =129; 
rect.left =0; 
rect.right =257; 
memDC.FillRect(&rect,&bhBack); //背景色是白色 //输出图片的内容 
//会员卡 和积分 strMsg=_T("多谢惠顾!"); 
memDC.TextOut(64,4,strMsg); strMsg.Format("本次金额:%d元",nThisPrice); 
memDC.TextOut(8,30,strMsg); //累计金额 
strMsg.Format("累计金额:%d元",nAcuPrice); 
memDC.TextOut(8,52,strMsg); strMsg.Format("会员卡号:%s",strVipCode); 
memDC.TextOut(8,74,strMsg); strMsg.Format("累计积分:%d",vipScore); 
memDC.TextOut(8,96,strMsg); 
bmpSave.GetBitmap(&bmpInfo); 
nWidth=bmpInfo.bmWidth; 
nHeight=bmpInfo.bmHeight; 
nLen=bmpInfo.bmWidthBytes *nHeight; 
unsigned char pData[32*160]; //保存bmp图的数据,因为宽度是256,所以32个 Byte,高度应该128,现在160是留多一些位置 
memset(pData,0,nLen); BITMAPINFO *pBITMAPINFO=(BITMAPINFO*)LocalAlloc(LPTR,sizeof(BITMAPINFOHEADER)+2*sizeof (RGBQUAD)); 
pBITMAPINFO->bmiHeader.biBitCount =1; 
pBITMAPINFO->bmiHeader.biClrImportant=0; 
pBITMAPINFO->bmiHeader.biCompression =0; 
pBITMAPINFO->bmiHeader.biHeight =nHeight; 
pBITMAPINFO->bmiHeader.biWidth =nWidth; 
pBITMAPINFO->bmiHeader.biPlanes =1; 
pBITMAPINFO->bmiHeader.biSize =sizeof(BITMAPINFOHEADER); 
pBITMAPINFO->bmiHeader.biSizeImage =nLen; 
pBITMAPINFO->bmiHeader.biXPelsPerMeter =0; 
pBITMAPINFO->bmiHeader.biYPelsPerMeter =0; 
//pBITMAPINFO->bmiHeader.biClrImportant =0; 
//pBITMAPINFO->bmiHeader.biClrUsed =2; 
//获得bmp图的 数据,并保存在 pData数组中 
GetDIBits(memDC.m_hDC,bmpSave,0,nHeight,pData,pBITMAPINFO,DIB_RGB_COLORS); 
//最后的动作,清除一些资源,也是我有疑虑的地方,不知道单清除这三个资源是否合适. 
memDC.DeleteDC(); 
pWnd->ReleaseDC(pDC); 
LocalFree(pBITMAPINFO); }

解决方案 »

  1.   

    弄一个For循环,然后在任务管理器里看资源状况,是否一直增长。
    ps:别忘了从任务管理器里的查看菜单下的选择列,把资源选出来观察。
      

  2.   

    bmpSave.CreateBitmap(256,128,1,1,NULL); 这个位图对象好像没释放       网上找下Bear.exe工具,能列举出详细的GDI各种对象的使用情况,
    你可以在调用之前和之后加个断点,察看你进程使用GDI情况,然后再继续运行察看GDI对象的变化。
    这样应该可以知道有没有泄露,以及具体泄露了什么对象。
      

  3.   

    谢谢IT_Fly 和 wangk 的指点,我先下载个Bear.exe来看看。
    利用任务管理器查看GDI对象,运行了十多次,发现没有增加.奇怪了,各位看看,还有没有什么招数?
      

  4.   


    makedisplaybmp用for循环一直执行,同时这个时候观察任务管理器,不是退出进程重新运行。
    如果这样资源依然保持稳定的话,那就基本没有资源泄漏的问题了。
      

  5.   

    在执行:memDC.DeleteDC(); 之前
    应该对其进行还原,选出你选入的所有gdi对象(位图、刷子、字体),这样才是安全的
    memDC.SelectObject(pOldBmp); 
    memDC.SelectObject(pOldFont); 
    memDC.SelectObject(pOldBrush); 
    MFC的gdi类的析构函数会自行进行deleteobject等操作,所以memDC.DeleteDC(); 并不是必须的
      

  6.   

    給你一段檢測的代碼
    #ifdef _DEBUG
    class CGuiResourceCheck
    {
        int m_gdi, m_user;
    public:
        CGuiResourceCheck()
        {
            m_gdi = GetGuiResources(GetCurrentProcess(), GR_GDIOBJECTS);
            m_user = GetGuiResources(GetCurrentProcess(), GR_USEROBJECTS);
        }    ~CGuiResourceCheck()
        {
            int gdi = GetGuiResources(GetCurrentProcess(), GR_GDIOBJECTS);
            int user = GetGuiResources(GetCurrentProcess(), GR_USEROBJECTS);        if (gdi != m_gdi || user!=m_user)
            {
                TRACE(_T("Resouce Difference: GDI_Ojects(%d -> %d), USER_Objects(%d -> %d)\n"), m_gdi, gdi, m_user, user);
            }
        }
    };
    #endif用法:
    bool makedisplaybmp(int nThisPrice,int nAcuPrice,int vipScore,CString strVipCode)

    #ifdef _DEBUG
        CGuiResourceCheck rescheck;
    #endif
        ......
    }
      

  7.   

    关于GDI资源管理的问题,你可以网上找下老外的代码DRAWGDIX.h,一整套管理GDI的类,使用对象来管理资源,你自己就不用费心了。
      

  8.   

    for循环和任务管理器查看的方法不错,挺直观的
      

  9.   

    应该不是很复杂吧,以前也写过类似功能的代码,比LZ这个要复杂。
    也没发现过内存泄漏的问题。仔细check一下,不要依赖于第三方工具。
      

  10.   

    谢谢各位的出手相助,目前,我是按照 ok1234567 兄的建议:选出我之前所选入的所有gdi对象,这样应该就不会有资源泄露了.