Утечка памяти в методе C ++ / CLI - PullRequest
1 голос
/ 07 марта 2012

Я обнаружил утечку памяти для этого вызова в моем коде:

BitmapSource snapshot = VideoPlayer.GetCurrentImage();

VideoPlayer - это библиотека C ++ / CLI, код для этого метода:

WriteableBitmap^ VideoPlayback::GetCurrentImage()
{
    BITMAPINFOHEADER bih;
    BYTE *pDib = 0;
    DWORD cbDib = 0;
    LONGLONG timeStamp = 0;

    memset(&bih, 0, sizeof(bih));
    bih.biSize = sizeof(BITMAPINFOHEADER);
    HRESULT hr = m_pPlayer->GetCurrentImage(&bih, &pDib, &cbDib, &timeStamp);

    if (FAILED(hr)) throw gcnew MFException(hr);

    WriteableBitmap^ res = ToWritableBitmap(bih, pDib, cbDib, true);

    CoTaskMemFree(pDib);

    return res;
}

и ToWriteableBitmap:

WriteableBitmap^ VideoPlayback::ToWritableBitmap(const BITMAPINFOHEADER& bih, BYTE* pDib, DWORD cbDib, bool bInvert)
{
    WriteableBitmap^ res;
    AtlTrace(_T("image size: %d x %d, bitCount: %d, bufferSize: %d\n"), bih.biWidth, bih.biHeight, bih.biBitCount, cbDib);

    switch (bih.biBitCount)
    {
        //could there be any other format!?
    case 24:
        //AtlTrace(_T("24bit image not supported!"));
        res = gcnew WriteableBitmap(bih.biWidth, bih.biHeight, 72.0, 72.0, System::Windows::Media::PixelFormats::Bgr24, nullptr);
        break;
    case 32:
        res = gcnew WriteableBitmap(bih.biWidth, bih.biHeight, 72.0, 72.0, System::Windows::Media::PixelFormats::Bgr32, nullptr);
        break;
    }
    if (res!=nullptr)
    {
        int stride = res->BackBufferStride;
        res->Lock();

        if (bInvert)
        {
            BYTE* pBuf = (BYTE*)res->BackBuffer.ToPointer();

            BYTE* pDest = pBuf + (bih.biHeight - 1) * stride;
            BYTE* pSrc = pDib;
            //the image is inverted
            for (int y = 0; y < bih.biHeight; y++)
            {
                memcpy(pDest, pSrc, stride);
                pSrc+=stride;
                pDest-=stride;
            }
        }
        else
        {
            BYTE* pDest = (BYTE*)res->BackBuffer.ToPointer();
            memcpy(pDest, pDib, bih.biSizeImage);
        }

        res->AddDirtyRect(System::Windows::Int32Rect(0, 0, bih.biWidth, bih.biHeight));
        res->Unlock();
    }   
    return res;
}

Вызов этого метода несколько раз приводит к "закреплению" некоторого объекта и большому количеству DeadThread, когда я запускаю !threads в windbg. Запустив !gcroot на этих мертвых нитях, я получаю:

DOMAIN (00000000036553A0): HANDLE (Закреплено): 5417c8: Корень: 0000000022423378 (System.Object []) ->
00000000125f0c08 (System.Collections.ArrayList) ->
0000000012d96950 (System.Object []) ->
0000000012e44460 (System.Windows.Media.MediaContext) ->
0000000012e43e80 (System.Windows.Threading.Dispatcher) ->
0000000012e30480 (System.Threading.Thread)

Где адрес System.Object[] всегда один и тот же.

Как правильно очистить после этого вызова, чтобы поток мог закончиться? Или это проблема с кодом C ++?

1 Ответ

0 голосов
/ 07 марта 2012

Проблема была в том, что я создавал BitmapSource в фоновом потоке.Как только я вызвал этот метод с помощью Dispatcher.Invoke, утечка потока исчезла.

...