.net C+中的内存泄漏+/CLI方法
我在我的代码中找到了此调用的内存泄漏:.net C+中的内存泄漏+/CLI方法,.net,c++-cli,com-interop,.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
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;
}
和可写入位图:
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;
}
WriteableBitmap^VideoPlayback::ToWritableBitmap(常量BitMapInfo头和bih,字节*pDib,DWORD cbDib,布尔bInvert)
{
可写位图^res;
AtlTrace(_T(“图像大小:%d x%d,比特数:%d,缓冲区大小:%d\n”)、bih.biWidth、bih.biHeight、bih.bibibittcount、cbDib);
开关(bih.BIBIT计数)
{
//还有其他格式吗!?
案例24:
//AtlTrace(_T(“不支持24位图像”);
res=gcnew WriteableBitmap(bih.biWidth、bih.biHeight、72.0、72.0、System::Windows::Media::PixelFormats::Bgr24、nullptr);
打破
案例32:
res=gcnew WriteableBitmap(bih.biWidth、bih.biHeight、72.0、72.0、System::Windows::Media::PixelFormats::Bgr32、nullptr);
打破
}
如果(res!=nullptr)
{
int stride=res->BackBufferStride;
res->Lock();
if(bInvert)
{
字节*pBuf=(字节*)res->BackBuffer.ToPointer();
字节*pDest=pBuf+(bih.biHeight-1)*步幅;
字节*pSrc=pDib;
//图像是倒置的
对于(int y=0;yBackBuffer.ToPointer();
memcpy(pDest、pDib、波黑比西泽马吉);
}
res->AddDirtyRect(系统::Windows::Int32Rect(0,0,bih.biWidth,bih.biHeight));
res->Unlock();
}
返回res;
}
多次调用此方法会导致某些对象被“固定”,并在运行时导致高死区线程数!windbg中的线程
。正在运行!gcroot
在这些死线程上我得到:
域(000000000 36553A0):句柄(固定):5417c8:根:
00000000 22423378(System.Object[])->00000000 125F0C08(System.Collections.ArrayList)->
00000000 12D96950(System.Object[])->
00000000 12E44460(System.Windows.Media.MediaContext)->
00000000 12E43E80(System.Windows.Threading.Dispatcher)->
00000000 12E30480(System.Threading.Thread) 其中
System.Object[]
的地址始终相同
在这个调用之后,我如何正确地清理线程才能完成?还是C++代码有问题? 问题是我在后台线程中创建了BITMAP源。有一次我使用Dispatcher.Invoke调用了这个方法,线程泄漏消失了。CLR使用固定对象数组来存储静态。我会在源代码中查找静态ArrayList。我认为您需要附加更多代码。我猜将是
到可写入位图
函数。它不会复制数据吗?你是说你有很多线程,但是你发布的代码中有线程。也许这是你应该研究的问题?@svick:我每次调用这个时都会创建一个新线程code@Krizz:添加了ToWritableBitmap函数。这是否意味着问题的根源是C++代码而不是C语言调用/清理?在C++/CLI调用返回指针以外的任何东西(我使用FreeCoTaskMem)之后,是否不需要释放内存?