请问.net托管堆在哪里?

liujichang1727 2010-01-26 10:03:25
今天偶然看到一篇文章谈.net内存分配机制,上面谈到引用类型存放于托管堆上,栈上只4字节(32位机器)存放引用类型的地址。应用程序实例化后,CLR将在进程的可用地址空间上分配一块内存区域,即为托管堆,但它不对应实际的物理内存。我的疑问就在这里了。栈对应实际的物理内存,堆不对应实际的物理内存吗?那托管堆中的变量、对象等到底是放在哪里?后来查资料看到有人说“托管堆是虚拟内存”,不知道正确与否,请问大虾们知道吗?
...全文
301 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
saturn4263195 2010-01-26
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 vrhero 的回复:]
胡说八道...托管堆不在内存里还会跑到火星去吗...
引用 MSDN:
初始化新进程时,运行时会为进程保留一个连续的地址空间区域。这个保留的地址空间被称为托管堆。托管堆维护着一个指针,用它指向将在堆中分配的下一个对象的地址。最初,该指针设置为指向托管堆的基址。托管堆上部署了所有引用类型。应用程序创建第一个引用类型时,将为托管堆的基址中的类型分配内存。应用程序创建下一个对象时,垃圾回收器在紧接第一个对象后面的地址空间内为它分配内存。只要地址空间可用,垃圾回收器就会继续以这种方式为新对象分配空间。

从托管堆中分配内存要比非托管内存分配速度快。由于运行时通过为指针添加值来为对象分配内存,所以这几乎和从堆栈中分配内存一样快。另外,由于连续分配的新对象在托管堆中是连续存储,所以应用程序可以快速访问这些对象。
[/Quote]
up
msq7487223 2010-01-26
  • 打赏
  • 举报
回复
up
vrhero 2010-01-26
  • 打赏
  • 举报
回复
胡说八道...托管堆不在内存里还会跑到火星去吗...
[Quote=引用 MSDN:]
初始化新进程时,运行时会为进程保留一个连续的地址空间区域。这个保留的地址空间被称为托管堆。托管堆维护着一个指针,用它指向将在堆中分配的下一个对象的地址。最初,该指针设置为指向托管堆的基址。托管堆上部署了所有引用类型。应用程序创建第一个引用类型时,将为托管堆的基址中的类型分配内存。应用程序创建下一个对象时,垃圾回收器在紧接第一个对象后面的地址空间内为它分配内存。只要地址空间可用,垃圾回收器就会继续以这种方式为新对象分配空间。

从托管堆中分配内存要比非托管内存分配速度快。由于运行时通过为指针添加值来为对象分配内存,所以这几乎和从堆栈中分配内存一样快。另外,由于连续分配的新对象在托管堆中是连续存储,所以应用程序可以快速访问这些对象。[/Quote]
fengyoujie 2010-01-26
  • 打赏
  • 举报
回复
帮楼主顶了。
liujichang1727 2010-01-26
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 cuike519 的回复:]
托管堆分配在被操作系统保留的一段内存区域中,这段内存区域是由CLR来管理的,这段内存称之为托管堆。
所谓的虚拟空间是指虚拟地址空间,每个应用程序在Windows默认的配置下都具有2G的内存空间,这些空间是逻辑上的,不是物理上的所以说是虚拟地址空间,当某一块地址要被CPU使用时,操作系统会按照某种算法将虚拟内存地址映射到物理地址上(提交),CPU永远是和物理内存通过地址总线连接的。

栈上的保存的是对象的引用(就是对象的实际地址)。

栈和堆都是逻辑结构,你不必考虑他们到底在物理内存中如何存储的,你要关心的是他们的逻辑地址,逻辑地址和物理地址之间的转换由操作系统完成。

栈的大小一般是固定的(1M),当函数一开始被调用操作系统按照配置(应用程序编译时指定的参数)来为函数建立一个固定大小的内存区域作为这个函数运行时的栈,函数的局部变量和参数都被压入栈,当函数调用结束之后栈应该刚好是空的(函数调用必须保证栈平衡)。
[/Quote]

看到这段话,我有点明白了。上午看到的那篇文章也没有说错,在程序初始化后,CLR开辟托管堆,这时候并不对应实际的物理内存,使用的是一种“虚拟地址空间”,待真正使用托管堆上的空间时,会将虚拟地址转换为实际物理地址。。。在最后,所有变量、对象肯定是放在内存上。OK,结贴。
shighui 2010-01-26
  • 打赏
  • 举报
回复
小伙说的不错。



一个系统如果同时运行着很多进程,为各进程分配的内存之和可能会大于实际可用的物理内存,虚拟内存管理使得这种情况下各进程仍然能够正常运行。因为各进程分配的只不过是虚拟内存的页面,这些页面的数据可以映射到物理内存页面,也可以临时保存到磁盘上而不占用物理内存页面,在磁盘上临时保存虚拟内存页面的可能是一个磁盘分区,也可能是一个磁盘文件,称为交换设备。
当物理内存不够用时,将一些不常用的物理页面中的数据临时保存到交换设备,然后这个物理页面就认为是空闲的了,可以重新分配给进程使用,这个过程称为换出。如果进程要用到被换出的页面,就从交换设备再加载回物理内存,这称为换入。换出和换入操作统称为换页,因此:
系统中可分配的内存总量 = 物理内存的大小 + 交换设备的大小
gghlkk 2010-01-26
  • 打赏
  • 举报
回复
一个系统如果同时运行着很多进程,为各进程分配的内存之和可能会大于实际可用的物理内存,虚拟内存管理使得这种情况下各进程仍然能够正常运行。因为各进程分配的只不过是虚拟内存的页面,这些页面的数据可以映射到物理内存页面,也可以临时保存到磁盘上而不占用物理内存页面,在磁盘上临时保存虚拟内存页面的可能是一个磁盘分区,也可能是一个磁盘文件,称为交换设备。
当物理内存不够用时,将一些不常用的物理页面中的数据临时保存到交换设备,然后这个物理页面就认为是空闲的了,可以重新分配给进程使用,这个过程称为换出。如果进程要用到被换出的页面,就从交换设备再加载回物理内存,这称为换入。换出和换入操作统称为换页,因此:
系统中可分配的内存总量 = 物理内存的大小 + 交换设备的大小
wuyq11 2010-01-26
  • 打赏
  • 举报
回复
.net CLR在运行我程序时,在内存中开辟托管堆.
托管堆用来存放引用类型.内存被组成连续的数组
cuike519 2010-01-26
  • 打赏
  • 举报
回复
托管堆分配在被操作系统保留的一段内存区域中,这段内存区域是由CLR来管理的,这段内存称之为托管堆。
所谓的虚拟空间是指虚拟地址空间,每个应用程序在Windows默认的配置下都具有2G的内存空间,这些空间是逻辑上的,不是物理上的所以说是虚拟地址空间,当某一块地址要被CPU使用时,操作系统会按照某种算法将虚拟内存地址映射到物理地址上(提交),CPU永远是和物理内存通过地址总线连接的。

栈上的保存的是对象的引用(就是对象的实际地址)。

栈和堆都是逻辑结构,你不必考虑他们到底在物理内存中如何存储的,你要关心的是他们的逻辑地址,逻辑地址和物理地址之间的转换由操作系统完成。

栈的大小一般是固定的(1M),当函数一开始被调用操作系统按照配置(应用程序编译时指定的参数)来为函数建立一个固定大小的内存区域作为这个函数运行时的栈,函数的局部变量和参数都被压入栈,当函数调用结束之后栈应该刚好是空的(函数调用必须保证栈平衡)。

110,536

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧