Memory leaks in C# while using C++/CLI defined class with finalizer(在终结器中使用C++/CLI定义的类时C#中的内存泄漏)
问题描述
当我在C++/CLI DLL中实现类时:
public ref class DummyClass
{
protected:
!DummyClass()
{
// some dummy code:
std::cout << "hello" << std::endl;
}
}
当我将DLL加载到C#项目并仅通过重复创建对象来使用该类时:
static void Main()
{
while (true)
{
var obj = new DummyClass();
}
}
然后,在运行该程序时,内存将慢慢消化为OutOfMemoryException。
似乎每次我在C++/CLI中实现终结器时都会发生这种内存泄漏(或垃圾回收的糟糕工作)。
为什么会发生这种内存泄漏?我如何才能避免它,同时仍能将终结器用于其他(更复杂的)用途?
update:原因肯定不是写入控制台/stdout或终结器中的其他非标准代码,以下类具有相同的内存泄漏行为:
public ref class DummyClass
{
private:
double * ptr;
public:
DummyClass()
{
ptr = new double[5];
}
protected:
!DummyClass()
{
delete [] ptr;
}
}
推荐答案
当分配速度超过垃圾收集速度时,您将遇到面向对象对象模型。如果您进行大量分配,CLR将插入一个睡眠(Xx)来限制分配,但在极端情况下这是不够的。
当您实现终结器时,您的对象将被添加到终结化队列中,当它被终结化时,它将从队列中删除。这确实会增加额外的开销,并且会使对象的寿命比必要的更长。即使您的对象可以在廉价的Gen 0GC期间被释放,它仍然被终结队列引用。当发生完全GC时,CLR确实会触发finalizaion线程开始清理。这没有任何帮助,因为您的分配速度确实快于您可以完成的速度(写入标准输出的速度非常慢),并且您的完成队列将变得越来越大,从而导致完成时间越来越慢。
我没有测量过它,但我认为即使是空的终结器也会导致此问题,因为增加的对象生存期和两个终结器队列处理(终结器队列和f-Reacable队列)确实会带来足够的开销,从而使终结器比分配慢。
您需要记住,终结是固有的异步操作,在特定时间点没有执行保证。在允许额外分配之前,CLR绝不会等待清除所有挂起的终结器。如果您分配给10个线程,那么在您之后仍会有一个终结器线程在清理。如果您希望依赖确定性终结,则需要通过调用EgWaitForPendingFinalizers()进行等待。 但这会让你的表演停滞不前。 因此,您的OOM是预期的。这篇关于在终结器中使用C++/CLI定义的类时C#中的内存泄漏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:在终结器中使用C++/CLI定义的类时C#中的内存泄漏


基础教程推荐
- rabbitmq 的 REST API 2022-01-01
- 将 XML 转换为通用列表 2022-01-01
- 有没有办法忽略 2GB 文件上传的 maxRequestLength 限制? 2022-01-01
- 将 Office 安装到 Windows 容器 (servercore:ltsc2019) 失败,错误代码为 17002 2022-01-01
- SSE 浮点算术是否可重现? 2022-01-01
- 如何在 IDE 中获取 Xamarin Studio C# 输出? 2022-01-01
- 为什么Flurl.Http DownloadFileAsync/Http客户端GetAsync需要 2022-09-30
- c# Math.Sqrt 实现 2022-01-01
- MS Visual Studio .NET 的替代品 2022-01-01
- 如何激活MC67中的红灯 2022-01-01