【问题标题】:The power of .NET without the garbage collection?没有垃圾收集的 .NET 的强大功能?
【发布时间】:2010-11-29 09:20:33
【问题描述】:

我喜欢 C#,因为 .NET 框架的强大功能使得在 Windows 上进行开发非常容易。不过,我也喜欢标准 C++,主要是因为它让我可以对内存管理进行微调控制。有没有两全其美的方法?是否有 C++ 库可以与 .NET 框架中丰富的库竞争?或者有没有办法以我从未使用过的一种 .NET 语言手动释放内存?或者是否可以在标准 C++ 应用程序中使用 .NET dll?我知道,我真的在这里伸展,但我相信魔法。

【问题讨论】:

  • 我认为你追求的是错误的目标。所有 .NET 库都依赖于 GC,因此对于内存,您将无法真正摆脱它。我建议您学习 C# 惯用的方法来为内存以外的任何东西实现 RAII 技术(IDisposable,使用)。 C# 是一种强大的语言。
  • 您还没有真正解释为什么要放弃 GC - 我想我们大多数人都会说 GC 是一件的事情。
  • C++ 的一个优点是,当你释放一些内存时,你知道它已经消失了,如果有东西试图再次访问该内存,就会发生明显的错误。使用垃圾收集器,一个对象可能根本不会被释放,因为一些其他未知对象正在引用它,从而导致微妙的内存泄漏而没有任何错误。所以在这种情况下,实际上可能更难调试内存泄漏,因为垃圾收集器有点太聪明了。
  • @Phil:你说在 C++ 中,“当你释放一些内存时......如果有东西试图再次访问该内存,就会发生明显的错误。”我不相信这是真的:释放后使用不是未定义的行为吗?对于手动管理的内存,我也可以想出很多方法来解决细微的错误,其中大多数会带来比内存泄漏更糟糕的后果。

标签: c# .net c++ memory-management garbage-collection


【解决方案1】:

这是您不需要 GC .NET 的原因之一;在 wp7 或即将推出的 win8 平板电脑上开发 XNA 游戏。如果您对对象分配不小心,GC 确实会产生断断续续的游戏体验,因为它会定期启动。通过对象池等可以解决它。但是,您无法控制所有创建的对象。所以不能保证对象会通过相同的池化机制。我可以想象一种特殊的 GC 模式,它会暂停收集,直到你告诉它继续。在 no-GC 模式下,它不会进行任何收集,但它会重用由对象释放的内存,而不是先等待收集。很像 C++ 内存管理器。它可以通过检查对象的内存区域是否应该立即可用来做到这一点。我确信实现它会比我在这里描述的更难,但是拥有这个特性是值得的,这样 .NET 开发人员就可以像游戏一样进行实时开发。

【讨论】:

    【解决方案2】:

    STL + Boost + Qt 是 C# 和 .NET 的有力竞争者。

    我最近不得不开发一个 Compact Framework 应用程序,与 Qt 的简单布局相比,我对 WinForms 方式感到失望。处理模式也很烦人,不清楚哪些资源需要处理,哪些不需要处理,所以我最终在谷歌上搜索什么是安全的 using() 。

    在我看来,unmanaged resource handling 比 C++ 的 RAII 更复杂。

    【讨论】:

      【解决方案3】:

      如果您真的想要显式访问指针等 (from MSDN),您还可以在 C# 中“固定”代码段:

      unsafe static void TestMethod()
      {
        // assume class Point { public int x, y; }
        // pt is a managed variable, subject to garbage collection.
        Point pt = new Point();
      
        // Using fixed allows the address of pt members to be
        // taken, and "pins" pt so it isn't relocated.
      
        fixed (int* p = &pt.x)
        {
            *p = 1;
        }        
      }
      

      但实际上,我认为您最好确定自己为什么要专门管理内存 —— 我认识的大多数开发人员宁愿专注于系统的实际设计和构建,而不是担心解除分配大块的记忆。这里还有其他很好的建议,比如 Boost(老实说,如果你有 cajones 宣称你比 GC 更好,那么你可能已经知道 Boost)、Qt 和 .NET 桥接(见鬼,如果愿意,您可以将 CLR 托管在非托管进程中),但我怀疑对于实际上可能需要您自己管理内存的少数地方,最好将它们限制在 VC++ 项目引用的其余的解决方案。

      【讨论】:

      • C++ 的一个优点是,当你释放一些内存时,你知道它已经消失了,如果有东西试图再次访问该内存,就会发生明显的错误。使用垃圾收集器,一个对象可能根本不会被释放,因为一些其他未知对象正在引用它,从而导致微妙的内存泄漏而没有任何错误。所以在这种情况下,实际上可能更难调试内存泄漏,因为垃圾收集器决定有点太聪明了。
      • 不过,我承认你的观点是完全不必担心内存管理,这在大多数情况下都非常有效。
      【解决方案4】:

      是否有 C++ 库可以 与丰富的图书馆竞争 在 .NET 框架中?

      QT 立即浮现在脑海,但我怀疑它是否像 .NET 库一样丰富。

      有没有办法手动解除分配 一种 .NET 语言的内存 我没用过?

      这个问题的答案是肯定的和否定的。.NET 中有一些方法可以控制内存。有weak references、强引用、(sort of) Forced Garbage collection 等。但这些东西已经在这里详细讨论过了。

      以下是有关 .NET 中的内存管理如何工作的一些详细信息。

      Garbage collection and generations
      Best practices of Forcing GC in .NET
      Better still, read the links in this search query

      是否可以在一个 .NET dll 中使用 标准 C++ 应用程序?

      是的,您可以为 .NET DLL 生成 COM 包装器/非托管包装器,并且可以在 C++ 应用程序中使用它。

      【讨论】:

        【解决方案5】:

        你看过Boost吗?

        或者,您可以使用“C++/CLI”(又名托管 C++,又名 C++.NET);用这种语言编写的代码可以调用 .NET API,也可以通过传统的 Win32 API(如 HeapAlloc/HeapFree)手动管理内存。不过,根据我的经验,这种语言最常用于编写“粘合代码”,而不是用于从头开始构建应用程序。

        【讨论】:

        • +1 用于 C++/CLI。 (我只添加了句点,因为 cmets 必须是 15 个字符长,只是想你们都想知道。现在有了这个评论,它的长度超过 15 个字符)
        • (当需要超过 15 个字符时,我会添加空格 :-))
        • 不,托管 C++ 是一个失败的实验,并且与 C++/CLI 源不兼容。但是,由于两者都是针对 .Net CLR 的语言,因此它们是二进制兼容的。 (VB.Net 和 C# 也是如此)
        【解决方案6】:

        您可以从托管代码调用非托管代码(通过 PInvoke),也可以从非托管代码调用托管代码(作为一种 COM 对象)。

        【讨论】:

          【解决方案7】:
          1. 您可以通过 COM 在 C++ 项目中使用 .NET dll,或者您可以托管 CLR 并与 CLR 实体交互,这将是非常麻烦的编码,但它是可能的。将 Com Visible 设置为 true 使 .NET 对象可以通过 VB/MFC 中的 COM 访问。

          2. .NET 几乎没有垃圾收集器的方法,您可以显式运行这些方法来收集垃圾,此外它还具有 IDisposable 接口,您可以使用该接口在类中处理您的成员,并且使用“using”关键字可以显式调用 dispose 方法在下面显示的使用示例结束时。

          using(FileStream fs = File.OpenRead("xyz.txt"){
             fs.Read(buff,0,100);
          }
          // here fs gets closed in dispose 
          //method automatically...
          
          1. Visual C++ CLI 项目可让您将常用的 C++ 和 .NET 集成到一个项目中。您可以在 Visual Studio 的各种应用程序向导中找到它。

          【讨论】:

            【解决方案8】:

            Qt 似乎是一个广泛的 C++ 类库。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2013-04-20
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多