gpt4 book ai didi

c# - c#应用程序中托管堆和 native 堆有什么区别

转载 作者:可可西里 更新时间:2023-11-01 07:45:37 25 4
gpt4 key购买 nike

从这里http://blogs.msdn.com/b/visualstudioalm/archive/2014/04/02/diagnosing-memory-issues-with-the-new-memory-usage-tool-in-visual-studio.aspx

  1. 托管:对于托管应用程序,分析器默认仅收集托管堆信息。托管堆分析是通过在分析器中捕获一组 CLR ETW 事件来完成的。
  2. native :对于 native 应用程序,分析器仅收集 native 堆信息。为了收集 native 堆信息,我们启用了堆栈跟踪和堆跟踪收集 (ETW),这些非常冗长并且会创建大型诊断 session 文件。

我的问题是在我的 c# 程序中(我只有带有 xaml 文件的 c# 代码)哪些类型的对象将进入托管堆,哪些类型进入 native 堆?以及如何在我的应用程序运行时指定每个堆的最大大小?我假设 GC 仅在托管堆上运行,对吗?

最佳答案

当您使用 C# 中的 new 运算符(或任何其他 CLR 语言中的相应运算符)创建对象时,.NET 运行时会在“托管堆”(由 .NET 运行时管理的堆 +垃圾收集器)。实际上,这是两个堆之一 - 一个用于大小小于 85K 的对象,另一个用于大于此大小的对象(大型数组等)。无论哪种方式,分配此类对象时,您都不会像在 native 代码中那样取回描述已分配空间地址的真实指针。你得到的是一个“句柄”,它代表对该内存地址的间接访问。这种间接存在是因为当 GC 收集并压缩堆时,实际的内存位置可能会发生变化。

但是,当您想与需要指针的非托管/ native 代码对话时,您需要使用指针,而不是句柄。 .NET 提供了两种方法将 .NET 句柄转换为可以传递给非托管代码的原始指针。

  1. 使用 Marshal.AllocHGlobal 在 NT(或 native 或非托管)堆上分配内存或 Marshal.AllocCoTaskMem并使用固定 block 或 IntPtr.ToInt32/ToInt64获取底层指针。请务必调用 Marshal.FreeHGlobal/Marshal.FreeCoTaskMem你自己或非托管代码正确释放内存(Windows 上的 FreeAlloc/CoTaskMemFree)。
  2. 如果您的数据是 blittable (与 native 代码互操作时可能就是这种情况),然后您可以简单地用 GCHandle.Alloc 固定此托管数据。然后使用从 GCHandle.AddrOfPinnedObject 获得的原始指针调用 native 代码, 完成后释放固定(使用 GCHandle.Free )。您还可以获得托管对象的实际底层指针地址,并临时固定在 C# 中的“fixed” block 内。

希望对您有所帮助!

关于c# - c#应用程序中托管堆和 native 堆有什么区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30723155/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com