内存分配不';C#应用程序结束时无法释放 我在Python模块周围有一个C++包装器,它在C++中工作得很好。也就是说,没有任何内存泄漏。我在C语言中暴露了C++函数,并将其应用到C语言应用中。然而,我注意到每当我结束C#应用程序时,分配的内存都不会被释放 讽刺的是,一切都是用Python来完成的,C++中没有内存分配,它只是调用Python对应的一系列方法,而在Python中,所有内存都由解释器管理。 Python模块基本上运行一个无限循环,其中使用网络摄像头提要,处理图像并将其发送回客户端(C#,C++)。Python中有一个Stop方法,它简单地设置一个值,该值在Python中结束这个循环,因此当这个循环结束时,实际上所有内容都结束了,从而被释放

内存分配不';C#应用程序结束时无法释放 我在Python模块周围有一个C++包装器,它在C++中工作得很好。也就是说,没有任何内存泄漏。我在C语言中暴露了C++函数,并将其应用到C语言应用中。然而,我注意到每当我结束C#应用程序时,分配的内存都不会被释放 讽刺的是,一切都是用Python来完成的,C++中没有内存分配,它只是调用Python对应的一系列方法,而在Python中,所有内存都由解释器管理。 Python模块基本上运行一个无限循环,其中使用网络摄像头提要,处理图像并将其发送回客户端(C#,C++)。Python中有一个Stop方法,它简单地设置一个值,该值在Python中结束这个循环,因此当这个循环结束时,实际上所有内容都结束了,从而被释放,c#,C#,旁注: 您看到的内存与加载到内存中的模型相关,该模型由Pytorch(Python中的一个深度学习框架)管理,因此在Python部分,我们只调用其他托管代码 C++,只调用这些方法,在Python或C++中没有任何问题,但是当涉及到C时,分配的内存不会被释放! 如果有关系,以下是我在C#上的DLLImport语句: [DllImport(@“Core_DLL.DLL”,CallingConvention=CallingConvention.Cdecl)] 公共静态外部初始化(boolshowf

旁注:
您看到的内存与加载到内存中的模型相关,该模型由
Pytorch
(Python中的一个深度学习框架)管理,因此在Python部分,我们只调用其他托管代码

C++,只调用这些方法,在Python或C++中没有任何问题,但是当涉及到C时,分配的内存不会被释放! 如果有关系,以下是我在C#上的

DLLImport
语句:

[DllImport(@“Core_DLL.DLL”,CallingConvention=CallingConvention.Cdecl)]
公共静态外部初始化(boolshowfeed);
[DllImport(@“Core_DLL.DLL”,CallingConvention=CallingConvention.Cdecl)]
公共静态外部无效启动(bool异步);
[DllImport(@“Core_DLL.DLL”,CallingConvention=CallingConvention.Cdecl)]
公共静态外部无效停止();
[DllImport(@“Core_DLL.DLL”,CallingConvention=CallingConvention.Cdecl)]
公共静态外部无效SetCpuAffinity(内部掩码);
[DllImport(@“Core_DLL.DLL”,CallingConvention=CallingConvention.Cdecl)]
公共静态外部bool GetVideoFeedDbgStatus();
[DllImport(@“Core_DLL.DLL”,CallingConvention=CallingConvention.Cdecl)]
公共静态外部无效设置VideoFeedDBGStatus(bool状态);
公共委托void CallbackDelegate(bool状态、字符串消息、IntPtr img、int行、int列);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
[DllImport(@“Core_DLL.DLL”,CallingConvention=CallingConvention.Cdecl)]
公共静态外部void AddCallback(IntPtr fn);
[DllImport(@“Core_DLL.DLL”,CallingConvention=CallingConvention.Cdecl)]
公共静态外部无效清除回调(IntPtr fn);
[DllImport(@“Core_DLL.DLL”,CallingConvention=CallingConvention.Cdecl)]
公共静态外部IntPtr GetCallbacks_str();
这是C#回调:

int op=0;
public void callback01(布尔状态、字符串id、IntPtr img_ptr、int行、int列)
{
这个状态=状态;
this.id=id;
int[]大小={rows,cols};
img=新垫(尺寸,MatType.CV_8UC3,img_ptr);
//这是为了保留图像,因为回调非常快
//当c#绘制它时,它将无效,因此您将得到
//扭曲的图像。所以我们在这里做一个深拷贝,这样我们就可以处理图像了
//以我们自己的速度!
img2=新材料();
img.CopyTo(img2);
//这允许在一个线程下执行所有互操作调用
开关(op)
{
案例1:
停止();
//MessageBox.Show(“完成”);
t、 中止();
打破
案例2:
Show(GetVideoFeedDbgStatus().ToString());
打破
违约:
打破
}
//重置标志
op=0;
}
启动方式:

线程t;
私有void btnRunService_单击(对象发送方,事件参数e)
{
tmrFetchStatus.Start();
t=新线程(新线程开始(()=>
{
RunService();
}));
t、 IsBackground=true;
t、 Start();
}
void RunService()
{
btnInit_单击(空,空);
启动(chkboxAsync.Checked);
}
私有void btnInit\u单击(对象发送方,事件参数e)
{
初始化(chkbxIShowFeed.Checked);
SetUpCallback();
tmrFetchStatus.Enabled=true;
}
这就是它的结局:

private void btnStop\u单击(对象发送方,事件参数e)
{
op=1;
}
C暴露的方法如下:

extern“C”
{
Core*Core=nullptr;
CORE_API int初始化(bool showFeed)
{
返回CreateHandle(showFeed)!=nullptr?0:1;
}
CORE_API无效启动(bool异步)
{
core=重新解释(GetHandle());
核心->启动(异步);
}
堆芯API无效停止(无效)
{
core=重新解释(GetHandle());
堆芯->停止();
}
CORE_API void AddCallback(CCallbackFn回调)
{
core->AddCallback\u C\u tmp(回调);
}
CORE_API void RemoveCallback(CCallbackFn回调)
{
core->RemoveCallback\u C\u tmp(回调);
}
std::字符串callbackLst;
CORE_API const char*GetCallbacks_str(无效)
{
core=重新解释(GetHandle());
自动结果=core->GetCallbacks_C_tmp();
//这是共享的,所以每次都要清除它。
callbackLst=“”;
用于(自动配对:结果)
{
callbackLst+=pair.first+“\r\n”;
}
//size\u t size=callbackLst.size()*sizeof(char)+1;
//字符*输出=新字符[大小];
//strcpy_s(输出、大小、callbackLst.c_str());
返回callbackLst.c_str();
}
CORE_API CCallbackFn*GetCallbacks()
{
core=重新解释(GetHandle());
自动结果=core->GetCallbacks_C_tmp();
size\u t size=results.size()*sizeof(CCallbackFn)+1;
CCallbackFn*callback_list=新的CCallbackFn[size];
int i=0;
用于(自动配对:结果)
{
回调_列表[i]=pair.second;
}
返回回调列表;
}
}

和使用/调用Python MO的C++部分