我有一種使用C++ DLL用佳能相機進行通信的應用,在該C++ DLL方法從C#應用程序調用。我在應用程序中看到的是,當拍照時,記憶會增加,當然。關閉「圖像捕捉窗口」後,應用程序仍會保留與所有圖像一樣的內存量。內存泄漏C++/C#應用
由於我的應用程序存在多層WPF UserControls,我認爲「圖像預覽UserControl」無法收集垃圾,因爲其他控件訂閱了從此控件觸發的事件。經過一番谷歌搜索之後,我決定對事件實施Weak Reference Pattern
。
//Source code found here: http://paulstovell.com/blog/weakevents
public sealed class WeakEventHandler<TEventArgs> where TEventArgs : EventArgs
{
private readonly WeakReference _targetReference;
private readonly MethodInfo _method;
public WeakEventHandler(EventHandler<TEventArgs> callback)
{
_method = callback.Method;
_targetReference = new WeakReference(callback.Target, true);
}
public void Handler(object sender, TEventArgs eventArgs)
{
var target = _targetReference.Target;
if (target != null)
{
var callback =
(Action<object, TEventArgs>)
Delegate.CreateDelegate(typeof (Action<object, TEventArgs>), target, _method, true);
if (callback != null)
{
callback(sender, eventArgs);
}
}
}
}
因此,如果我忘記取消訂閱一些活動,GC將收集它們。一些經過測試,這種方法沒有工作,所以我決定用Redgate ANTS Memory Profiler
我花了三年的快照:
- 拍攝圖像
- 之前,我花了後4個圖像
- 的破壞以後WPF的控制器比較快照1和3時
其結果是:
正如你可以看到分配的非託管內存的量是很大的問題在這裏。我首先想到的是,當「圖像捕捉窗口」關閉時,C++ DLL不會釋放分配的內存。
我是正確的問題是在C++插件?我可以排除C#應用程序嗎?據我所知,所有用.NET編寫的代碼都是託管內存。
基於這裏的註釋是圖像從C++插件的C#插件如何到達:
從C++插件有這樣的回調:
_resultcallback(img->GetImageInfo().Data, img->GetImageInfo().Width, img->GetImageInfo().Height, img->GetImageInfo().BPP);
而且方法其接收關於C#側的圖像:
private void OnResultImageCallback(IntPtr imagePtr, int width, int height, int bitsPerPixel)
{
_state = CameraState.InitializedStandby;
_cbResultData.Width = width;
_cbResultData.Height = height;
_cbResultData.BitsPerPixel = bitsPerPixel;
int memSize = bitsPerPixel * width * height/8;
_cbResultData.data = new byte[memSize];
Marshal.Copy(imagePtr, _cbResultData.data, 0, memSize);
_deleteAllocatedImageFunction(imagePtr);
if (ImageCaptured != null)
ImageCaptured(_cbResultData.data, _cbResultData.Width, _cbResultData.Height, _cbResultData.BitsPerPixel);
_cbResultData.data = null;
}
我也有以清除在我的C++,其TA所分配的存儲器的方法KES在字節指針這樣的:
BOOL CanonEDSDKWnd::ClearImageBuffer(BYTE* img) {
_debug->Write(_T("CanonEDSDKWnd::ClearImageBuffer"));
delete[] img;
return TRUE;
}
,其從與所述IntPtr
從回調
_deleteAllocatedImageFunction(imagePtr)C#代碼調用;
如何圖像到達從C C#代碼++圖書館?如何調用非託管方法?如何將圖像存儲在託管端?沒有關於代碼的知識,很難說任何有用的東西。 – 2014-10-28 08:31:14
請參閱我的編輯。我認爲它應該是必不可少的部分。 – 2014-10-28 08:38:06
我很確定回調中的'img'指向的對象必須以某種方式被釋放。你應該有一個C++函數來刪除img,並且在將數據複製到託管存儲之後應該調用它。 – 2014-10-28 08:47:05