CLI本机对象卡在gen2中,而不是垃圾收集
本文关键字:对象 本机 gen2 CLI | 更新日期: 2023-09-27 18:13:28
我正在研究这个高频生产系统。有一个c#/CLI层调用一个c++库。我们观察到的是,托管对象进入了垃圾收集器的第2代,并被"卡住"了。最终,随着内存耗尽,c#应用程序陷入停顿。这些托管对象是本地对象,应该具有非常短的生存期。而且它们只被引用一次。c#应用程序必须对所有拥有本机资源的对象调用. dispose(),以确保所有内容都被强制删除。我们有相当多的对象,所以这不是理想的,从API的角度来看是混乱的。命令行如下所示:
Field::~Field()
{
if(m_pField != NULL)
{
delete m_pField;
m_pField = NULL;
}
System::GC::SuppressFinalize(this);
}
Field::!Field()
{
if(m_pField != NULL)
{
delete m_pField;
}
}
谁能想到为什么这些短寿命的对象似乎永远不会被收集和释放内存?
问题是非托管对象不计入GC用来决定何时进行垃圾收集的"内存压力"值。
你可以做的一件事是使用GC.AddMemoryPressure(
让GC知道有一个大的非托管对象与你的托管包装相关。
Field::Field()
{
//... Other stuff
if(m_pField != NULL)
{
m_lSizeOfField = GetSizeOfField(m_pField);
System::GC::AddMemoryPressure(m_lSizeOfField);
}
}
Field::~Field()
{
//If you had managed objects you would call "delete" here on them.
//delete m_managedData;
//In C++/CLI if you have unmanged resources just have the dispose method
// call the finalizer. It is cleaner and easier to maintain.
// You can't do this in C#
this->!Field();
//No need to add this next line, C++/CLI does it for you.
//System::GC::SuppressFinalize(this);
}
Field::!Field()
{
if(m_pField != NULL)
{
delete m_pField;
m_pField = NULL;
System::GC::RemoveMemoryPressure(m_lSizeOfField);
}
}