2

我们有一个 C++ 库(没有 MFC,没有 ATL),它为我们的 .NET 应用程序提供了一些核心功能。SWIG使用 C++ DLL生成 C# 程序集,该程序集可用于使用 PInvoke 访问其类/方法。这个 C# 程序集在我们的 .NET 应用程序中用于使用 C++ DLL 中的功能。

该问题与内存泄漏有关。在我们的 .NET 应用程序中,我的 .NET 代码中有一个循环,它从 C++ DLL 创建特定类的数千个实例。循环在创建实例时不断减慢,但如果我在循环内调用 GC.Collect() (我知道不建议这样做),处理速度会更快。为什么是这样?对类型调用 Dispose() 对速度没有任何影响。我预计使用 GC.Collect() 会降低程序速度,但事实恰恰相反。

SWIG 生成的每个类都有一个调用 Dispose() 的 ~destructor。每个 Dispose 方法在调用以释放非托管内存的语句周围都有一个 lock(this)。最后它调用 GC.SuppressFinalize。我们还在 Release 版本中偶尔看到 AccessViolationException。任何帮助将不胜感激。

4

2 回答 2

1

Finalize如果某些类型的对象在没有被处理的情况下被丢弃,它们可以自行清理(通过),但是在终结器找到它们之前保留它们的成本可能很高;框架中的一个示例是由Microsoft.VisualBasic.Collection.GetEnumerator(). 每次调用GetEnumerator()都会将一个由新枚举器对象包装的对象附加到集合管理的各种私有更新事件上,当枚举器为Disposed 时,它将取消订阅其事件。如果GetEnumerator()被调用多次(例如数千或数百万)而没有释放枚举器并且没有干预垃圾收集,随着事件订阅列表的不断增长,收集将变得越来越慢(比正常慢数百或数千倍)。然而,一旦发生垃圾收集,任何废弃的枚举器的Finalize方法都会清理它们的订阅,并且事情将再次开始正常工作。

我知道您说过您正在调用Dispose,但我怀疑某些东西正在创建一个IDisposable对象实例而不是调用Dispose它。如果IDisposableclassFoo创建并拥有IDisposableclass的实例Bar,但该实例Foo不在Dispose其自己的Dispose实现中,则调用Dispose的实例Foo不会清理Bar. 一旦实例 ofFoo被放弃,无论它是否被Disposed,它Bar最终都会被放弃而没有处置。

于 2012-09-21T18:00:17.393 回答
0

你在 Dispose 方法中调用 GC.SupressFinalize 吗?无论如何,有一篇很好的 MSDN 文章解释了如何编写 GC 友好的代码 -垃圾收集基础和性能提示。也许它会有用。

于 2012-09-20T06:03:12.877 回答