2016-01-21 48 views
1

我正在尋找此代碼中的內存泄漏。 我是GDI +的新手,我不確定我做錯了什麼。 您在下面看到的類在我的主函數中被循環調用。 每次循環迭代我將其他向量推送到該函數。 除了存在內存泄漏,一切正常。 我試過程序cppCheck找到泄漏,但沒有發現任何內存泄漏:/ 我最後的機會來解決這個問題是問別人誰與GDI有更多的經驗比我+C++ GDI +自己的類中的內存泄漏

非常感謝您的幫助和遺憾的長碼:)

#include "helper.h" 

Gui::Gui(const TCHAR* fileName) { 
    this->fileName = fileName; 
} 

void Gui::drawGui(Gdiplus::Bitmap* image, std::vector<std::wstring> &vec) { 

    // Init graphics 
    Gdiplus::Graphics* graphics = Gdiplus::Graphics::FromImage(image); 

    Gdiplus::Pen penWhite (Gdiplus::Color::White); 
    Gdiplus::Pen penRed (Gdiplus::Color::Red); 
    Gdiplus::SolidBrush redBrush(Gdiplus::Color(255, 255, 0, 0)); 
    penRed.SetWidth(8); 

    unsigned short marginTop = 15; 
    unsigned short marginLeft = 5; 
    unsigned short horizontalBarsizeStart = marginLeft + 60; 


    for (unsigned short iter = 0; iter < 8; iter++) { 
     // Draw text 
     std::wstring coreLabel = L"Core " + std::to_wstring(iter) + L':'; 
     Gdiplus::Font myFont(L"Arial", 12); 
     Gdiplus::PointF origin(marginLeft, marginTop - 10); 
     graphics->DrawString(coreLabel.c_str(), coreLabel.length(), &myFont, origin, &redBrush); 

     // Draw CPU lines 
     unsigned short horizontalBarsizeEnd = horizontalBarsizeStart + std::stoi(vec.at(iter)); // 100 == Max cpu load 
     graphics->DrawLine(&penRed, horizontalBarsizeStart, marginTop, horizontalBarsizeEnd, marginTop); 

     // Draw border 
     Gdiplus::Rect rect(horizontalBarsizeStart, marginTop - 5, 100, 8); 
     graphics->DrawRectangle(&penWhite, rect); 

     // Next element 
     marginTop += 17; 
    } 
} 


bool Gui::SetColorBackgroundFromFile(std::vector<std::wstring> &vec) { 

    Gdiplus::GdiplusStartupInput gdiplusStartupInput; 
    ULONG_PTR gdiplusToken; 
    // Initialize GDI+. 
    Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); 

    HDC hdc = GetDC(NULL); 

    // Load the image. Any of the following formats are supported: BMP, GIF, JPEG, PNG, TIFF, Exif, WMF, and EMF 
    Gdiplus::Bitmap* image = Gdiplus::Bitmap::FromFile(this->fileName, false); 

    if (image == NULL) { 
     return false; 
    } 

    // Draw the gui 
    this->drawGui(image, vec); 

    // Get the bitmap handle 
    HBITMAP hBitmap = NULL; 
    Gdiplus::Status status = image->GetHBITMAP(RGB(0, 0, 0), &hBitmap); 
    if (status != Gdiplus::Ok) { 
     return false; 
    } 

    BITMAPINFO bitmapInfo = { 0 }; 
    bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 

    // Check what we got 
    int ret = GetDIBits(hdc, hBitmap, 0, 0, NULL, &bitmapInfo, DIB_RGB_COLORS); 

    if (LOGI_LCD_COLOR_WIDTH != bitmapInfo.bmiHeader.biWidth || LOGI_LCD_COLOR_HEIGHT != bitmapInfo.bmiHeader.biHeight) { 
     std::cout << "Oooops. Make sure to use a 320 by 240 image for color background." << std::endl; 
     return false; 
    } 

    bitmapInfo.bmiHeader.biCompression = BI_RGB; 
    bitmapInfo.bmiHeader.biHeight = -bitmapInfo.bmiHeader.biHeight; // this value needs to be inverted, or else image will show up upside/down 

    BYTE byteBitmap[LOGI_LCD_COLOR_WIDTH * LOGI_LCD_COLOR_HEIGHT * 4]; // we have 32 bits per pixel, or 4 bytes 

    // Gets the "bits" from the bitmap and copies them into a buffer 
    // which is pointed to by byteBitmap. 
    ret = GetDIBits(hdc, hBitmap, 0, 
    -bitmapInfo.bmiHeader.biHeight, // height here needs to be positive. Since we made it negative previously, let's reverse it again. 
    &byteBitmap, 
    (BITMAPINFO *)&bitmapInfo, DIB_RGB_COLORS); 

    LogiLcdColorSetBackground(byteBitmap); // Send image to LCD 

    // delete the image when done 
    if (image) { 
     delete image; 
     image = NULL; 
     Gdiplus::GdiplusShutdown(gdiplusToken); // Shutdown GDI+ 
    } 
return true; 
} 

回答

3

drawGui()你泄露graphics對象。該行創建了一個新的Gdiplus::Graphics對象:

Gdiplus::Graphics* graphics = Gdiplus::Graphics::FromImage(image); 

但無處你叫delete graphics刪除它,一旦你用它做。

SetColorBackgroundFromFile中,您泄漏了DC。

HDC hdc = GetDC(NULL); 

這得到了DC的屏幕,但無處你叫ReleaseDC(NULL, hdc);釋放它。

在相同的功能,您使用的是下面的調用創建HBITMAP

Gdiplus::Status status = image->GetHBITMAP(RGB(0, 0, 0), &hBitmap); 

但無處你叫DeleteObject(hBitmap);釋放它。

您還有問題,如果出現錯誤,您的代碼可能會返回而無需進行必要的清理。例如。如果GetHBITMAP調用失敗,則立即返回,並將泄漏您在上面創建的幾行的image對象。

+0

目前爲止完美:)但ReleaseDC(hdc);不工作 –

+0

@TheCoder對不起,應該是'ReleaseDC(NULL,hdc);' –

+0

非常感謝你,你救了我一天! –