2017-07-25 1 views
0

j'appelle à plusieurs reprises ce code obtenir une fuite de mémoire:Gdiplus :: :: Bitmap fuite de mémoire FromHBITMAP

ULONG_PTR gdiplusToken; 
int screen_height; 
int screen_width; 

CVCamStream::CVCamStream(HRESULT *phr, CVCam *pParent, LPCWSTR pPinName) : CSourceStream(LPCSTR(FILTER_NAME),phr, pParent, pPinName), m_pParent(pParent) 
{ 
    hdc = GetDC(NULL); 

    Gdiplus::GdiplusStartupInput gdiplusStartupInput; 
    ULONG_PTR gdiplusToken; 
    GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); 

    screen_height = GetSystemMetrics(SM_CYVIRTUALSCREEN); 
    screen_width = GetSystemMetrics(SM_CXVIRTUALSCREEN); 
} 

CVCamStream::~CVCamStream() 
{ 
    Gdiplus::GdiplusShutdown(gdiplusToken); 
    DeleteDC(hdc); 
} 

HRESULT CVCamStream::FillBuffer(IMediaSample *pms) 
{ 
    REFERENCE_TIME rtNow; 
    REFERENCE_TIME avgFrameTime = ((VIDEOINFOHEADER*)m_mt.pbFormat)->AvgTimePerFrame; 

    static clock_t refClock = clock(); 
    double elapsed = (clock() - refClock)/(double)CLOCKS_PER_SEC; 

    rtNow = m_rtLastTime; 
    m_rtLastTime += avgFrameTime; 
    pms->SetTime(&rtNow, &m_rtLastTime); 
    pms->SetSyncPoint(TRUE); 

    HDC memdc = CreateCompatibleDC(NULL); 

    CImage image; 
    image.Create(screen_width, screen_height, 24); 
    SelectObject(memdc, image); 

    BYTE *pData; 
    pms->GetPointer(&pData); 
    long lDataLen = pms->GetSize(); 

    Gdiplus::Bitmap *bitmap = new Gdiplus::Bitmap(screen_width, screen_height, PixelFormat24bppRGB); 

    BitBlt(memdc, 0, 0, screen_width, screen_height, hdc, 0, 0, SRCCOPY); 
    DeleteDC(memdc); 

    // memdc is already deleted 
    bitmap->FromHBITMAP(image, NULL); 

    delete bitmap; 
    image.Destroy(); 
    DeleteObject(image); 
    DeleteDC(memdc); 

    return NOERROR; 
} 

Mais chaque fois que les augmentations d'utilisation de la RAM. La ligne incriminée est la fonction FromHBITMAP(), car il n'y a plus de fuite.

Je sais FromHBITMAP() crée une copie de l'image bitmap mais je pensais que je libère tous les souvenirs!

Quel est le problème ici?

+2

Ce code ne compile pas. Le type 'bitmap' est incorrect. Si c'est un pointeur (deviné par 'new' init) alors vous devriez le supprimer. De plus, il n'y a pas de nettoyage pour 'hdc'. – VTT

+0

Correction de la faute de frappe et mise à jour du code: la fuite de mémoire est toujours là. – Mark

+0

Peut-être existe-t-il un autre moyen de capturer le contenu de l'écran dans un bitmap GDi +? – Mark

Répondre

0

FromHBITMAP ne prend pas en charge le handle de bitmap transmis. Vous pouvez simplement passer un handle de bitmap qui sera toujours détenu par l'instance CImage. Aussi according to MSDN:

ne passent pas à la méthode de Bitmap :: FromHBITMAP un bitmap GDI ou une palette GDI qui est actuellement (ou précédemment) sélectionné dans un contexte de périphérique.

Et vous l'appelez pendant que image est toujours sélectionné dans memdc.

+0

Je dois utiliser 'memdc' pour' BitBlt() '. J'ai essayé de le supprimer avant d'appeler 'FromHBITMAP' et j'ai aussi changé le' image.Detach() 'en image. Même comportement – Mark

+0

La première chose que cette image est encore sélectionnée dans DC quand il ne devrait pas être. Le code posé est-il réellement complet? Vous avez ajouté des notes sur le destructeur et le constructeur, donc je suppose qu'il y a plus de code qui n'est pas affiché ici. – VTT

+0

S'il vous plaît, regardez le code mis à jour. Le code "caché" n'était pas lié à la manipulation de l'image. – Mark