跨C#和C ++ / CLI对象的垃圾收集

时间:2012-01-06 12:41:29

标签: c# garbage-collection c++-cli

我目前正在寻求使用C ++ / CLI来弥合托管C#和本机非托管C ++代码之间的差距。我希望解决的一个特殊问题是转换C#和C ++中不同的数据类型。

在阅读这种桥接方法的使用以及所涉及的性能影响时,我想知道垃圾收集如何工作。具体来说,垃圾收集器如何处理在任何一方创建的对象的清理,如果它们在另一方被引用/销毁'。

到目前为止,我已经在StackOverflowMSDN上阅读了各种文章和论坛问题,这让我相信垃圾收集器在运行时应该可以在两种类型的代码中工作相同的过程 - 即如果一个对象是在C#中创建并传递给C ++ / CLI桥,则在双方的引用不再使用之前不会收集它。

在这种情况下,我的问题分为三部分:

  1. 我是否正确地得出结论,垃圾收集器在同一个进程中运行时跨代码的两个部分(C#和C ++ / CLI)工作?
  2. 关于1:在这种情况下它是如何工作的(特别是在清理两个代码库引用的对象方面)。
  3. 是否有关于如何监控垃圾收集器活动的建议 - 即编写测试以检查垃圾收集何时发生;或监视垃圾收集器本身的程序。
  4. 我已经对垃圾收集器的工作原理有了一些了解,所以我的问题特定于以下场景:

    零件

    • 程序集A - (用C#编写)
    • 程序集B - (用C ++ / CLI编写)

    程序执行

    1. 对象O程序集A
    2. 中创建
    3. 对象O传递到程序集B 内的函数。
    4. 发布程序集A 中对象O的引用。
    5. 程序集B 保留对对象O的引用。
    6. 执行结束(即通过程序退出)。
    7. 程序集B 会释放对象O的引用。
    8. 提前感谢您对此问题的任何想法。如果需要进一步的信息或者某些内容不够清楚,请告诉我。

      修改

      根据要求,我已经写了一个我试图描述的场景的粗略示例。可以在PasteBin上找到C#C++/CLI代码。

2 个答案:

答案 0 :(得分:4)

当代码实际运行时,它们都不是C#或C ++ / CLI。所有这些都是来自C#和C ++ / CLI的IL以及来自您正在与之互操作的本机代码的机器代码。

因此,您可以将部分问题重写为:

  • 装配A - (IL,我们不知道它写的是什么)
  • 装配B - (IL,我们不知道它写的是什么)

在托管对象中,所有托管对象都将按照相同的规则进行垃圾回收,除非您使用机制来阻止它(GC.KeepAlive)。所有这些都可以在内存中移动,除非你固定它们(因为你将地址传递给非托管代码。

.NET Profiler将为您提供有关垃圾收集的一些信息,以及性能监视器中的收集计数。

答案 1 :(得分:1)

  

我是否正确地得出结论垃圾收集器可以兼顾两者       在同一进程中运行时代码的一部分(C#和C ++ / CLI)?

是的,单个垃圾收集器在一个进程内工作(C#和托管C ++)。如果在一个进程中有代码在不同的CLR版本下运行,那么每个CLR版本将有不同的GC实例

  

关于1:在这种情况下它是如何运作的(具体而言)       在清理两个代码库引用的对象方面)。

我认为对于GC,如果代码是托管C#或C ++ / CLI并不重要(请注意,GC只管理C#和托管C ++代码而不是本机C ++)。它将以自己的方式工作,而不考虑底层的代码类型。关于释放内存,只要无法再引用对象,GC就会这样做。因此,只要存在引用变量的内容,无论汇编如何都不会收集它。对于本机C ++代码,您必须手动释放每个动态分配的内存

  

是否有关于如何监控垃圾活动的建议       收集器 - 即编写测试以检查何时发生垃圾收集;要么       一个监视垃圾收集器本身的程序。

您可以使用.Net Profiler等工具进行监控。另请查看Garbage Collection Notifications