CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 8 of 8
  1. #1
    Join Date
    Apr 2009
    Posts
    1,355

    [RESOLVED] [win32 and GUID/GUID+] - how avoid memory leaks?

    i understand that everytime, that i create an object, i must destroy it:
    HCURSOR with LoadImage() - DestroyCursor()
    until here fine.
    i'm doing an image class, but i have some memory leaks and i don' understand how resolve them

    before continue 1 have 1 question: if the class destructor is called when the class is destroyed, why i lose the image(on menus), if i DeletObject() HBITMAP on destructor? for me, don't make sence

    i'm confused why i get memory leaks, but see the class:
    Code:
    class image
    {
    private:
        ULONG_PTR m_gdiplusToken;
        Gdiplus::GdiplusStartupInput gdiplusStartupInput;
        HDC hdcimage=CreateCompatibleDC(NULL);
        HGDIOBJ obj=NULL;
        HBITMAP btBitmap;
        Gdiplus::Graphics *graphic;
        Image *img;
        int imageheight=0;
        int imageweight=0;
        int framecount=0;
        int intSelectFrame=0;
        int framedelay=0;
        string strfilename="";
        Gdiplus::Color clrBackColor=Gdiplus::Color::Transparent;
        HDC hdcwindow;
        bool blnTransparent=true;
    
    public:
    
        image()
        {
            Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);
            btBitmap=CreateCompatibleBitmap(hdcimage,1,1);
            obj = SelectObject(hdcimage, btBitmap);
        }
    
        image(HDC hdcWindow)
        {
            Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);
            hdcwindow=hdcWindow;
        }
    
        image(int width, int height)
        {
            Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);
            hdcimage = CreateCompatibleDC(NULL);
            btBitmap = CreateCompatibleBitmap(hdcimage,width,height);
            obj = SelectObject(hdcimage, btBitmap);
            framecount=1;
        }
    
        image( const string & filename)
        {
            strfilename=filename;
            Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);
            if(toupper(filename[filename.size()-3])=='C' && toupper(filename[filename.size()-2])=='U' && toupper(filename[filename.size()-1])=='R')
            {
                //create the transparent icon handle
                HCURSOR hicon = (HCURSOR)LoadImage(NULL, filename.c_str(), IMAGE_CURSOR, imageweight, imageheight, LR_LOADFROMFILE|LR_SHARED|LR_DEFAULTSIZE|LR_LOADTRANSPARENT);
                ICONINFO ii;
                BOOL fResult = GetIconInfo(hicon, &ii);
                if (fResult)
                {
                    BITMAP bm;
                    fResult = GetObject(ii.hbmMask, sizeof(bm), &bm) == sizeof(bm);
                    if (fResult)
                    {
                        imageweight= bm.bmWidth;
                        imageheight= ii.hbmColor ? bm.bmHeight : bm.bmHeight / 2;
                    }
                    if (ii.hbmMask) DeleteObject(ii.hbmMask);
                    if (ii.hbmColor) DeleteObject(ii.hbmColor);
                }
                btBitmap=CreateBitmap(imageweight,imageheight,1,32,NULL);//create the bitmap with icon size
                obj = SelectObject(hdcimage, btBitmap);//add the bitmap to memory DC
                DrawIconEx(hdcimage,0,0,hicon,imageweight,imageheight,0,0,DI_NORMAL);//draw the icon to DC with right size
                //seems the DrawIcon(), always, draw it with 32X32 size
                framecount=1;
                DestroyCursor(hicon);
            }
            else
            {
                Gdiplus::Image img2(towstring(filename).c_str());
                btBitmap=CreateBitmap(img2.GetWidth(),img2.GetHeight(),1,32,NULL);
                obj = SelectObject(hdcimage, btBitmap);
                Gdiplus::Graphics graphics(hdcimage);
                graphics.DrawImage(&img2, 0, 0, img2.GetWidth(), img2.GetHeight());
                imageweight=img2.GetWidth();
                imageheight=img2.GetHeight();
                UINT count = 0;
                count = img2.GetFrameDimensionsCount();
                GUID* pDimensionIDs = (GUID*)malloc(sizeof(GUID)*count);
                img2.GetFrameDimensionsList(pDimensionIDs, count);
                framecount=img2.GetFrameCount(&pDimensionIDs[0]);
                if (framecount>1)
                    framedelay =img2.GetPropertyItemSize(PropertyTagFrameDelay);
                else
                    framedelay =0;
                img=new Image(towstring(filename).c_str());
                free(pDimensionIDs);
            }
        }
    
        image (const image &cSource)
        {
            Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);
            framecount=cSource.framecount;
            framedelay=cSource.framedelay;
            clrBackColor=cSource.clrBackColor;
            img=cSource.img->Clone();
            imageweight=cSource.imageweight;
            imageheight=cSource.imageheight;
            strfilename=cSource.strfilename;
            btBitmap=CreateBitmap(imageweight,imageweight,1,32,NULL);
            obj = SelectObject(hdcimage, btBitmap);
            BitBlt(hdcimage,0,0,imageweight,imageheight,cSource.hdcimage,0,0,SRCCOPY);
        }
    
        image& operator= (const image &cSource)
        {
            framecount=cSource.framecount;
            framedelay=cSource.framedelay;
            intSelectFrame=cSource.intSelectFrame;
            clrBackColor=cSource.clrBackColor;
            imageweight=cSource.imageweight;
            imageheight=cSource.imageheight;
            btBitmap=CreateBitmap(imageweight,imageweight,1,32,NULL);
            obj = SelectObject(hdcimage, btBitmap);
            BitBlt(hdcimage,0,0,imageweight,imageheight,cSource.hdcimage,0,0,SRCCOPY);
            return *this;
        }
    
        property <int> SelectFrame
        {
            Get(int)
            {
                return intSelectFrame;
            },
            Set(int selectframe)
            {
                intSelectFrame=selectframe;
                UINT count = 0;
                count = img->GetFrameDimensionsCount();
                GUID* pDimensionIDs = (GUID*)malloc(sizeof(GUID)*count);
                img->GetFrameDimensionsList(pDimensionIDs, count);
                img->SelectActiveFrame(&pDimensionIDs[0],intSelectFrame);
                graphic=new Graphics(hdcimage);
                graphic->Clear(clrBackColor);
                graphic->DrawImage(img, 0, 0, img->GetWidth(), img->GetHeight());
                free(pDimensionIDs);
            }
        };
    
        property<int> FramesCount
        {
            Get(int)
            {
                return framecount;
            }
        };
    
        property<string> FileName
        {
            Get(string)
            {
                return strfilename;
            },
            Set(string filename)
            {
                strfilename=filename;
                if(toupper(filename[filename.size()-3])=='C' && toupper(filename[filename.size()-2])=='U' && toupper(filename[filename.size()-1])=='R')
                {
                    //create the transparent icon handle
                    HCURSOR hicon = (HCURSOR)LoadImage(NULL, filename.c_str(), IMAGE_CURSOR, imageweight, imageheight, LR_LOADFROMFILE|LR_SHARED|LR_DEFAULTSIZE|LR_LOADTRANSPARENT);
                    ICONINFO ii;
                    BOOL fResult = GetIconInfo(hicon, &ii);
                    if (fResult)
                    {
                        BITMAP bm;
                        fResult = GetObject(ii.hbmMask, sizeof(bm), &bm) == sizeof(bm);
                        if (fResult)
                        {
                            imageweight= bm.bmWidth;
                            imageheight= ii.hbmColor ? bm.bmHeight : bm.bmHeight / 2;
                        }
                        if (ii.hbmMask) DeleteObject(ii.hbmMask);
                        if (ii.hbmColor) DeleteObject(ii.hbmColor);
                    }
                    btBitmap=CreateBitmap(imageweight,imageheight,1,32,NULL);//create the bitmap with icon size
                    obj = SelectObject(hdcimage, btBitmap);//add the bitmap to memory DC
                    DrawIconEx(hdcimage,0,0,hicon,imageweight,imageheight,0,0,DI_NORMAL);//draw the icon to DC with right size
                    //seems the DrawIcon(), always, draw it with 32X32 size
                    framecount=1;
                    DestroyCursor(hicon);
                }
                else
                {
                    Gdiplus::Image img2(towstring(filename).c_str());
                    btBitmap=CreateBitmap(img2.GetWidth(),img2.GetHeight(),1,32,NULL);
                    obj = SelectObject(hdcimage, btBitmap);
                    Gdiplus::Graphics graphics(hdcimage);
                    graphics.DrawImage(&img2, 0, 0, img2.GetWidth(), img2.GetHeight());
                    imageweight=img2.GetWidth();
                    imageheight=img2.GetHeight();
                    UINT count = 0;
                    count = img2.GetFrameDimensionsCount();
                    GUID* pDimensionIDs = (GUID*)malloc(sizeof(GUID)*count);
                    img2.GetFrameDimensionsList(pDimensionIDs, count);
                    framecount=img2.GetFrameCount(&pDimensionIDs[0]);
                    framedelay =img2.GetPropertyItemSize(PropertyTagFrameDelay);
                    img=new Image(towstring(filename).c_str());
                    free(pDimensionIDs);
                }
            }
        };
    
        property<Gdiplus::Color> Backcolor
        {
            Get(Gdiplus::Color)
            {
                return clrBackColor;
            },
            Set(Gdiplus::Color bkcolor)
            {
                clrBackColor = bkcolor;
                SetDCBrushColor(hdcimage,clrBackColor.ToCOLORREF());
            }
        };
    
        void draw(HDC control)
        {
            //if (clrBackColor.GetValue() == Gdiplus::Color::Transparent)
            if (clrBackColor.GetValue()== Gdiplus::Color::Transparent)
            {
                TransparentBlt(control, 0, 0,width(),height(),hdcimage, 0, 0,width(), height(), GetPixel(hdcimage,width()-1,height()-1));
            }
            else
            {
                BitBlt(control,0,0,width(),height(),hdcimage,0,0,SRCCOPY);
            }
            //InvalidateRect(WindowFromDC(control),NULL,false);
        }
    
        operator HBITMAP()
        {
            return btBitmap;
        }
    
        int height()
        {
            return imageheight;
        }
    
        int width()
        {
            return imageweight;
        }
    
        operator HDC()
        {
            return hdcimage;
        }
    
        ~image()
        {
            delete btBitmap;
            DeleteObject(obj);
            delete img;
            Gdiplus::GdiplusShutdown(m_gdiplusToken);
            //DeleteObject(btBitmap);//don't show me the image
            DeleteDC(hdcimage);
        }
    };
    what anyone can tell me?

  2. #2
    VictorN's Avatar
    VictorN is offline Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Hanover Germany
    Posts
    20,398

    Re: [win32 and GUID/GUID+] - how avoid memory leaks?

    Quote Originally Posted by Cambalinho View Post
    i'm confused why i get memory leaks, but see the class:
    Code:
    class image
    {
    ...
        property <int> SelectFrame
        {
            Get(int)
            {
                return intSelectFrame;
            },
            Set(int selectframe)
            {
                ...
                graphic=new Graphics(hdcimage);
                graphic->Clear(clrBackColor);
                graphic->DrawImage(img, 0, 0, img->GetWidth(), img->GetHeight());
                free(pDimensionIDs);
            }
        };
    
        ~image()
        {
            delete btBitmap;
            DeleteObject(obj);
            delete img;
            Gdiplus::GdiplusShutdown(m_gdiplusToken);
            //DeleteObject(btBitmap);//don't show me the image
            DeleteDC(hdcimage);
        }
    };
    what anyone can tell me?
    You create graphic with new but never delete it.
    You do NOT create btBitmap with new.So why do you delete it?
    Victor Nijegorodov

  3. #3
    Join Date
    Apr 2009
    Posts
    1,355

    Re: [win32 and GUID/GUID+] - how avoid memory leaks?

    Quote Originally Posted by VictorN View Post
    You create graphic with new but never delete it.
    You do NOT create btBitmap with new.So why do you delete it?
    i understand what you mean, but see the destructor with comments:
    Code:
    ~image()
        {
            delete btBitmap;//don't give me problems..
            delete graphic; //memory leak, when i excute the aplication
            DeleteObject(obj);
            delete img;
            Gdiplus::GdiplusShutdown(m_gdiplusToken);
            //DeleteObject(btBitmap);//don't show me the image on menus, when i execute the aplication
            DeleteDC(hdcimage);
        }
    so where is the problem?

  4. #4
    VictorN's Avatar
    VictorN is offline Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Hanover Germany
    Posts
    20,398

    Re: [win32 and GUID/GUID+] - how avoid memory leaks?

    Quote Originally Posted by Cambalinho View Post
    i understand what you mean, but see the destructor with comments:
    Code:
    ~image()
        {
            delete btBitmap;//don't give me problems..
            delete graphic; //memory leak, when i excute the aplication
            DeleteObject(obj);
            delete img;
            Gdiplus::GdiplusShutdown(m_gdiplusToken);
            //DeleteObject(btBitmap);//don't show me the image on menus, when i execute the aplication
            DeleteDC(hdcimage);
        }
    so where is the problem?
    1. It doesn't matter whether deleting something that you did not new gives you any problem in this particular code. You must not delete what you did not new delete. Point.

    2. If you still get the leaks because of the graphic despite you do
    Code:
            delete graphic; //memory leak, when i excute the aplication
    in the dtor, then you, probably create more than onc of the B]graphic[/B] objects but you delete only one of them.
    Set break point on the
    Code:
       graphic=new Graphics(hdcimage);
    line, start debugging and see how many times it will be called for the same .image object.
    Victor Nijegorodov

  5. #5
    Join Date
    Apr 2009
    Posts
    1,355

    Re: [win32 and GUID/GUID+] - how avoid memory leaks?

    everytime, before i change the btBitmap,after the constructos, i delete the HBITMAP objects:
    Code:
    //on FileName property
    //......
    Set(string filename)
            {
                delete graphic;
                delete img;
                DeleteObject(btBitmap);
                DeleteObject(obj);
    //.....................
    but on destructor i can't delete the graphic,but i changed it. i don't use the new keyword now. and if i delete the object btBitmap, the image isn't showed.
    so the problem isn't the times that i use the new keyword.
    Last edited by Cambalinho; January 19th, 2015 at 10:04 AM.

  6. #6
    Join Date
    Apr 2009
    Posts
    1,355

    Re: [win32 and GUID/GUID+] - how avoid memory leaks?

    ok... you have right. now i don't need delete the graphic, because i don't use the new keyword. but why i can't delete the objetc btBitmap?(i lose the image)

  7. #7
    VictorN's Avatar
    VictorN is offline Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Hanover Germany
    Posts
    20,398

    Re: [win32 and GUID/GUID+] - how avoid memory leaks?

    Quote Originally Posted by Cambalinho View Post
    everytime, before i change the btBitmap,after the constructos, i delete the HBITMAP objects:
    Code:
    //on FileName property
    //......
    Set(string filename)
            {
                delete graphic;
                delete img;
                DeleteObject(btBitmap);
                DeleteObject(obj);
    //.....................
    but on destructor i can't delete the graphic,but i changed it. i don't use the new keyword now.
    ... and there is no more memory leaks?

    Quote Originally Posted by Cambalinho View Post
    if i delete the object btBitmap, the image isn't showed.
    so the problem isn't the times that i use the new keyword.
    Sure it won't be shown since you have deleted the bitmap to be shown!

    PS. Do you also have the resource leaks?
    Victor Nijegorodov

  8. #8
    Join Date
    Apr 2009
    Posts
    1,355

    Re: [win32 and GUID/GUID+] - how avoid memory leaks?

    Quote Originally Posted by VictorN View Post
    ... and there is no more memory leaks?

    Sure it won't be shown since you have deleted the bitmap to be shown!

    PS. Do you also have the resource leaks?
    i did more tests, with diferent images, and no more more leaks.
    thanks for all
    Last edited by Cambalinho; January 19th, 2015 at 10:37 AM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured