C# 分配非托管资源的位置

C# 分配非托管资源的位置,c#,garbage-collection,C#,Garbage Collection,我不是一个搞计算机科学的人。托管资源在堆上分配。但我想知道非托管资源的分配位置。如果堆上也分配了非托管资源,那么托管资源使用的是同一个堆还是不同的堆 提前谢谢 哈沙在内存中。与任何非托管进程一样。。托管堆显然不同于托管堆。从操作系统的角度来看,堆本质上是相同的:分配给操作系统进程的内存空间 不同之处在于,当CLR(.net VM)在Windows进程内加载时,它会从该堆中取出一部分,并将其转换为托管堆。该内存空间将成为分配所有托管资源的地方,并为垃圾收集器所知 例如,如果分配了一大块非托管内存,

我不是一个搞计算机科学的人。托管资源在堆上分配。但我想知道非托管资源的分配位置。如果堆上也分配了非托管资源,那么托管资源使用的是同一个堆还是不同的堆

提前谢谢


哈沙在内存中。与任何非托管进程一样。。托管堆显然不同于托管堆。

从操作系统的角度来看,堆本质上是相同的:分配给操作系统进程的内存空间

不同之处在于,当CLR(.net VM)在Windows进程内加载时,它会从该堆中取出一部分,并将其转换为托管堆。该内存空间将成为分配所有托管资源的地方,并为垃圾收集器所知

例如,如果分配了一大块非托管内存,并且托管堆的空间不足,则可能会遇到内存不足错误。或者反过来说

杰弗里·里克特(Jeffrey Richter)是更好地解释这件事的人。我强烈建议阅读他的解释:


您可以使用System.InteropServices命名空间的服务,特别是类,在堆的非托管部分和托管部分之间复制数据

CLR维护自己的堆。最初,创建两个:一个简单地称为(或小对象堆),另一个是(另请参见)。这些托管堆在物理上与CRT分配的用于
new
malloc
的本机堆分开


您可以使用来检查进程分配的不同堆。

借用一篇杂志文章中比较线性和非线性过滤器的话,比较托管资源和非托管资源就像比较袋鼠生物学和非袋鼠生物学一样

在.net中,托管资源是托管堆上的类对象。总是。值类型可以保存对托管资源的引用,但值类型实例本身不能“是”托管资源

相比之下,非托管资源可以是任何东西,也可以存储在任何地方。它不需要与拥有它的程序在同一台计算机上,甚至不需要在同一个星球上(我不知道发送到火星的任何探测器都会暴露任何类型的通信套接字接口,这些接口会表现为非托管资源,但人们肯定可以设计它们这样做)


如果某个外部实体代表某个对象执行某项操作而损害了其他实体的利益,则该对象将持有非托管资源,并且将一直执行该操作,直到被告知停止(或者,可能直到超时)。有许多种非托管资源,它们几乎可以存在于任何地方。其中一些(例如锁和事件订阅)可能完全存在于.net的托管世界中。其中一些(例如服务器连接)可能存在于任何给定时刻“拥有”它们的计算机之外。某些类型的非托管资源可能封装来自操作系统的内存块,与非托管堆分开,但非托管资源没有“存储”的一般位置。相反,如前所述,非托管资源可以是任何东西,也可以存储在任何地方。

要使用非托管堆操作,请使用MSDN中描述的封送处理类


非托管堆不受GC控制,所以内存使用的所有责任都在您身上。本质上,要释放分配给非托管资源的内存,请使用IDisposable接口并自行释放所有分配的资源。所有非托管资源(如SQL连接和不同的IO操作)都使用这种方法。

这篇文章非常好。为了完整起见,我还添加了第二部分。@Oliver:太好了!谢谢你编辑了这个问题,而不是仅仅把它发布在评论中。是的,当你赢得足够的声誉时,这是一个很好的特性(就像你已经做的一样)。;)实际上,非托管资源可以在任何地方——不一定在封装资源的对象所在的机器上。离机资源的两个常见示例是远程服务器上的文件,或到资源非常有限的设备的TCP连接(例如,许多嵌入式设备一次只支持一个TCP连接)。如果例程获取这样一个文件或TCP连接而不立即释放它,那么它可能会使其他机器上的用户至少暂时无法访问这样的资源。否。请参阅“远程服务器上的文件”仍在本地分配以进行管理。要使其保持打开状态,您需要一个文件共享,该文件共享附带显示不符合逻辑,它绑定到本地服务器的文件管理堆栈上的文件打开操作。TCP连接也以某种方式使用本地套接字。虽然大多数操作系统都会管理TCP套接字和远程文件句柄之类的东西,并在应用程序退出时清理它们,但缺少的是远程计算机上的资源。本地计算机的操作系统保留对远程文件的引用,并且可以在应用程序退出时清除该引用,这并不意味着其他计算机上的用户(他们既不知道也不关心与打开该文件的计算机有关的任何事)将无法访问远程计算机上的文件,直到发生这种情况。