【问题标题】:Do I need to dispose of SWIG-generated objects?我需要处理 SWIG 生成的对象吗?
【发布时间】:2017-05-18 18:13:14
【问题描述】:

我目前正在使用从 SWIG 构建到 .NET 的库。该库的文档似乎没有提供有关是否需要处理或需要处理哪些类的任何信息。我还在其他论坛上看到了关于需要添加代码来处理我在这个库的源代码中没有看到的子元素的讨论。除此之外,该库的示例项目和测试不包括usings,也不释放它们创建的对象。

那么,对于“平均”SWIG 对象,我是否需要处理它?似乎它们都有默认的析构函数,可以删除底层 C++ 中的对象。如果是这种情况,那么我是否可以将它们视为任何其他对象并让垃圾收集器处理它们(禁止阻止垃圾收集器正确处理它们的事情,例如循环引用和其他经典内存泄漏)。不得不用某种处置上下文或其他东西将所有调用/对象包装到这个库中,这很糟糕。

【问题讨论】:

  • 循环引用不会阻止对象被丢弃。
  • SWIG 是否向 c# 对象添加了终结器?如果没有,您可能会发生内存泄漏,因为 GC 不能保证在所有情况下都会调用 Dispose。
  • 这取决于如何使用 SWIG 创建包装器。包装对象有很多可能性,您需要手动处理。同时正如@JoelLucsy 解释的那样,可以制作包装器,使生成的代码包含终结器,从而确保正确的 gc。
  • @Servy 循环引用防止对象被终结,并且 SWIG 添加了终结器来处理。
  • @NateDiamond - 循环引用不会阻止对象被终结(和释放),它们延迟对象被终结。无论如何,一旦一个对象无法从所有 GC 根中访问,它最终将被最终确定并 GC'd。唯一的例外是当您通过在终结器中执行一些愚蠢的操作(例如尝试获取锁)来死锁终结器线程时。

标签: c# swig idisposable


【解决方案1】:

鉴于 cmets 中的答案,在我的情况下似乎总体上没有必要。 SWIG 生成了适当的终结器,它调用了 dispose 函数。可能是 SWIG 定义中的 dispose 函数定义不正确,但如果是这种情况,那么手动 dispose 无论如何也无济于事。

编辑:虽然最初断言不需要处理对象,但在某些情况下它可能有用。

考虑通过 SWIG 公开列表对象的情况:List 此外,您还有一个列表拥有的“项目”对象:Item

如果你这样做:

List list = new List(1, 2, 3);
Item item = list.Get(1);
// list is now available for garbage collection, as there are no longer any P/invokes nor 
// references to it
item.GetValue(); // Can possibly throw AccessViolationException if list
                 // has been garbage collected based on how it cleans up its items.

为防止这种情况发生,您必须防止list 被最终确定/处置,直到所有items 都用完之后。这可以通过以下几种方式完成:

  • items 的所有使用结束时使用GC.KeepAlive()。例如

    item.GetValue();

    GC.KeepAlive(list);

  • 利用IDisposable 模式确保父对象的确定性处置。例如

using(List list = new List(1, 2, 3))
{
    Item item = list.Get(1);
    item.GetValue();
}

因此手动处理或使用IDisposable 模式本身必需,但确保您对非托管对象的使用安全、一致和清晰会很有用。

【讨论】:

  • 在使用示例中,是什么阻止了父对象在item.GetValue()之前被销毁? GC不还是可以提前收集的吗?
  • 一般来说,GC 会保持对象处于活动状态,直到它不再被使用。 using 语句被编译成一个 try/finally 块,最后带有 Dispose 调用,从而保证对代码块末尾之外的对象进行调用。如前所述,另一种选择是使用具有类似效果的GC.KeepAlive,但有些人可能更喜欢using 块的消歧性。
  • @StayOnTarget 也只是对您所做的编辑感到好奇。我原本想避免使用“List”,部分原因是它应该表示一个非托管集合对象(并且不要与内置的 List 类型混淆)。如果真的更可取,也许将名称更改为UnmanagedList?否则,IMO 回到 Collection 就不会那么混乱了。
  • 我可能应该在编辑时留下评论。当我读到它时,我在使用“收集”作为数据结构与垃圾收集之间有点困惑。由于数据结构的具体性质似乎不太重要,我认为将其称为列表将有助于避免这种歧义。具体来说,我并不是说它看起来像 .NET 列表。哦,我也认为变量名(“c”与“collection”)有一个小的拼写错误或变化,但这是次要的。
猜你喜欢
  • 2013-09-23
  • 2011-02-23
  • 1970-01-01
  • 1970-01-01
  • 2012-04-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多