C ++ / CLI方法中的内存泄漏

时间:2012-03-06 21:59:53

标签: .net c++-cli com-interop

我在我的代码中跟踪了此调用的内存泄漏:

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;
}

当我在windbg中运行!threads时,多次调用此方法会导致某些对象被“固定”并且死线计数很高。我在这些死线程上运行!gcroot

  

DOMAIN(00000000036553A0):手柄(销接):5417c8:根:   0000000022423378(System.Object的[]) - &GT;
  00000000125f0c08(System.Collections.ArrayList) - &GT;
  0000000012d96950(System.Object的[]) - &GT;
  0000000012e44460(System.Windows.Media.MediaContext) - &GT;
  0000000012e43e80(System.Windows.Threading.Dispatcher) - &GT;
  0000000012e30480(System.Threading.Thread)

System.Object[]的地址始终相同。

如何在此次通话后正确清理以便线程完成?或者它是C ++代码的问题?

1 个答案:

答案 0 :(得分:0)

问题是我在后台线程中创建了BitmapSource。一旦我使用Dispatcher.Invoke调用此方法,线程泄漏就消失了。