我在我的代码中跟踪了此调用的内存泄漏:
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 ++代码的问题?
答案 0 :(得分:0)
问题是我在后台线程中创建了BitmapSource。一旦我使用Dispatcher.Invoke调用此方法,线程泄漏就消失了。