iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > ASP.NET >.NET中堆栈和堆的特点与差异介绍
  • 708
分享到

.NET中堆栈和堆的特点与差异介绍

2024-04-02 19:04:59 708人浏览 八月长安
摘要

一、前言 .net提供了垃圾回收机制,使程序员从内存管理中被解放出来。但这并不代表程序员就无须了解分配的对象是如何被回收的。更重要的是,一些非托管的资源仍然需要程序员小心地分配与回收

一、前言

.net提供了垃圾回收机制,使程序员从内存管理中被解放出来。但这并不代表程序员就无须了解分配的对象是如何被回收的。更重要的是,一些非托管的资源仍然需要程序员小心地分配与回收。

理解堆和堆栈是理解内存管理的基础。每一个.NET程序都最终会运行在一个操作系统进程中,假设这个操作系统是传统的32位的,那每个.NET程序都可以拥有一个4GB的虚拟内存。.NET会在这个4GB的内存块中开辟出三块内存分别作为堆栈、受托管的堆和非托管的堆。

二、.NET中的堆栈

.NET中的堆栈用来存储值类型的对象和引用类型对象的引用,堆栈的分配是连续的,在.NET程序中,始终存储了一个特殊的指针指向堆栈的尾部,这样一个堆栈内存的分配就直接从这个指针指向的内存位置开始向下分配。下图展示了.NET的堆栈分配方式。

如上图所示,堆栈上的地址从高位开始往低位分配内存,.NET只需要保存一个堆栈指针指向下一个未分配内存的内存地址。对于所有需要分配的对象,依次分配到堆栈中,其释放也严格按照栈的逻辑,依次进行退栈。这里提到的“依次”,是指按照变量的作用域进行的。考虑下面的代码:

ClassA a = new ClassA();
a.intA = 1;
a.intB = 2;

这里假设ClassA是一个引用类型,则堆栈中依次需要分配的是a的引用、a.intA和a.intB。当a的作用域结束后,这三个变量则从堆栈中依次退出:a.intB、a.intA,然后才是a。

三、.NET中的托管堆

接下来我们看一下托管的堆。.NET中的引用类型对象是分配在托管堆上的。通常我们称.NET中的堆,指的就是托管的堆。和堆栈一样,托管的堆也是进程内存空间中的一块区域。但托管堆中的内存的分配却和堆栈有很大的区别。受益于.NET的内存管理机制,托管堆的分配也是连续的,但是堆中存在着暂时不能被分配却已经无用的对象内存块。当一个引用类型对象被初始化时,就会通过指向堆上可用空间的指针分配一块连续的内存,然后使堆栈上的引用指向堆上的这块内存块。下图展示了堆的分配方式。

如上图所示,程序通过分配在堆栈中的引用来找到分配在托管堆的对象实例。当堆栈区域中的引用退出作用域时,就仅仅断开引用和实际对象的联系。而当托管堆中的内存不够时,.NET开始执行垃圾回收。垃圾回收是一个非常复杂的过程,它不仅涉及托管堆中对象的释放,而且需要移动合并托管堆中的内存块。当垃圾回收后,堆内不被使用的对象才会被部分释放,而在这之前,它们在堆内是暂时不可用的。

四、.NET中的非托管堆

.NET的程序还包含了非托管的堆,所有需要分配堆内存的非托管资源将会被分配到非托管堆上。非托管的堆需要程序员用指针手动地分配并且手动地释放,.NET的垃圾回收和内存管理制度不适用于非托管的堆。

五、堆栈、托管堆和非托管堆的比较

堆栈、托管堆和非托管堆的分配各有特点。堆栈的内存是连续分配的,按照作用域依次分配和释放。堆栈的机制非常简单,.NET依靠一个堆栈指针就可以进行内存操作,分配一个对象和释放一个对象的大部分操作就是自增或者自减堆栈指针。.NET中的值类型对象和引用类型对象的引用是分配在堆栈内的。

托管堆的内存分配虽然也是连续的,但它却比堆栈复杂得多。一块堆内存的分配需要涉及很多.NET内存管理机制的内部操作,另外当堆内存不够时,垃圾回收的执行代价也是非常大的。相对于堆栈来说,堆的分配效率低得多。.NET中的引用类型对象是分配在托管堆上的,这些对象通过分配在堆栈上的引用来进行访问。

非托管堆和托管堆的区别在于非托管堆不受.NET的管理。非托管堆的内存是由程序员手动分配和释放的,垃圾回收机制不适用于非托管堆,内存块也不会被合并移动,所以非托管堆的内存分配按块的,不连续的。

六、总结

.NET程序在进程内存中分配出堆栈、托管堆和非托管堆。所有的值类型对象和引用类型对象的引用都分配在堆栈上,堆栈根据对象的生存周期来依次分配和释放,堆栈根据一个指向栈尾的指针来分配内存,效率很高。

.NET所有的引用类型对象分配在托管堆上,托管堆连续分配内存,并且受.NET的垃圾收集机制管理,受托管堆的内存分配和释放涉及复杂的内存管理,效率相对于堆栈来说低得多。

需要分配堆内存的非托管类型将被分配在非托管堆上,非托管堆不受.NET垃圾收集机制管理,内存块完全由程序员手动申请和释放。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程网。

--结束END--

本文标题: .NET中堆栈和堆的特点与差异介绍

本文链接: https://www.lsjlt.com/news/143351.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • .NET中堆栈和堆的特点与差异介绍
    一、前言 .NET提供了垃圾回收机制,使程序员从内存管理中被解放出来。但这并不代表程序员就无须了解分配的对象是如何被回收的。更重要的是,一些非托管的资源仍然需要程序员小心地分配与回收...
    99+
    2024-04-02
  • 深入探讨Golang中堆栈的差异
    Golang是一门广受欢迎的编程语言,其在并发编程方面拥有独特的设计理念。在Golang中,堆栈(heap和stack)的管理是一项非常重要的任务,对于理解Golang程序的运行机制至...
    99+
    2024-03-13
    golang 堆栈 差异
  • C语言堆栈帧的介绍与创建
    什么是堆栈帧?        堆栈帧(stack frame)是一块堆栈保留区域,用于存放被传递的实际参数,子程序的返回...
    99+
    2024-04-02
  • C语言堆栈帧的介绍与创建方式
    本篇内容主要讲解“C语言堆栈帧的介绍与创建方式”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“C语言堆栈帧的介绍与创建方式”吧!什么是堆栈帧?    &nb...
    99+
    2023-06-20
  • Golang编程中堆与栈的异同分析
    堆与栈是计算机内存中两种常见的数据存储方式,它们在Golang编程中起着重要的作用。本文将从概念、特点、存储结构以及使用方面对堆与栈进行详细的比较分析,并结合具体的Golang代码示例...
    99+
    2024-03-13
    golang
  • Pythonnumpy和matlab的几点差异介绍
    目录numpy和matlab的几点差异1、Numpy数组索引指定开始和结束时2、Numpy.ndarray切片的修改会引起原矩阵的修改3、numpy使用切片索引(例如1:2)不会产生...
    99+
    2024-04-02
  • C++中堆和栈问题的分析与解决方案
    C++中堆和栈问题的分析与解决方案在C++编程中,堆和栈是两种常用的内存管理方式。堆用于动态分配内存,而栈则用于存储局部变量和函数调用的上下文信息。然而,错误的使用堆和栈可能导致内存泄漏、段错误和无法预料的行为。因此,在编写C++代码时需要...
    99+
    2023-10-22
    内存管理 (Memory management) 栈溢出 (Stack Overflow) 堆分配 (Heap allo
  • Golang中协程与线程的特性和差异分析
    Golang中协程和线程的特点与区别分析 一. 引言Golang是一门现代化的编程语言,以其简洁、高效和并发性而闻名。在Golang中,协程和线程是实现并发编程的两种主要方式。本文将分析协程和线程的特点与区别...
    99+
    2024-01-24
    Golang 线程 协程
  • PHP中的数组有哪些常用操作方式?与NumPy的相同点和差异是什么?
    PHP中的数组是一种非常常见的数据类型,可以存储多个值,并且可以通过索引访问和操作数组中的元素。在本文中,我们将介绍PHP中的数组常用操作方式,并将其与NumPy进行比较,以便更好地理解它们之间的相同点和差异。 一、PHP中的数组常用操作方...
    99+
    2023-08-26
    数组 numpy spring
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作