"揭秘.NET内存奥秘:从CIL深处窥探值类型与引用类型的生死较量,一场关于速度与空间的激情大戏!"

简介: 【9月更文挑战第2天】

由浅入深CIL系列:3.通过CIL观察.NET值类型和引用类型的内存分配

在.NET框架中,内存分配机制是理解程序性能与资源管理的基础。CIL(公共中间语言),作为.NET编译过程中的关键一环,为我们提供了一个独特的视角来观察和理解这一机制。本文将通过CIL代码示例,详细探讨.NET中值类型和引用类型的内存分配情况。

首先,我们从一个简单的C#程序开始,通过编译后的CIL代码来分析其内存分配机制。以下是一个简单的C#程序示例:

csharp
class Program
{
static void Main(string[] args)
{
int a = 3;
int b = 19;
double c = 443.25;
Console.WriteLine(a + b + c);

    string d = "Hello World!";  
    string e = "Print Word!";  
    Console.WriteLine(e);  
    Console.WriteLine(d);  
    Console.WriteLine(d + e);  
}  

}
值类型的内存分配
当我们编译上述C#代码并查看其CIL表示时,可以看到值类型(如int和double)的内存分配方式。在CIL中,值类型的实例如果作为方法中的局部变量,则它们会被直接存储在调用该方法的线程的堆栈上。以下是CIL代码中与值类型分配相关的部分:

cil
// 值类型内存存储情况
IL_0001: ldc.i4.3 // 将整数值 3 作为 int32 推送到计算堆栈上
IL_0002: stloc.0 // 将堆栈顶部的 3 弹出并存储到局部变量 a
IL_0003: ldc.i4.s 19 // 将整数 19 作为 int32 推送到计算堆栈上
IL_0005: stloc.1 // 将堆栈顶部的 19 弹出并存储到局部变量 b
IL_0006: ldc.r8 443.25 // 将 double 值 443.25 推送到计算堆栈上
IL_000f: stloc.2 // 将堆栈顶部的 443.25 弹出并存储到局部变量 c
从上面的CIL代码中可以看出,值类型的分配和存储是直接在堆栈上进行的,这意味着它们的访问速度非常快,因为堆栈操作通常比堆操作要快。同时,值类型的生命周期与它们所在的栈帧紧密相关,一旦栈帧被销毁,其上的所有值类型变量也将随之销毁。

引用类型的内存分配
与值类型不同,引用类型的实例通常存储在托管堆(Managed Heap)上,无论是GC堆还是LOH(Large Object Heap)。在CIL中,当我们创建一个引用类型的实例时,会通过newobj指令在堆上分配内存,并将引用(即对象的内存地址)存储在堆栈上。以下是CIL中与引用类型分配相关的部分:

cil
// 引用类型内存存储情况
IL_001c: ldstr "Hello World!" // 为字符串 "Hello World!" 分配内存,并推送其引用到堆栈
IL_0021: stloc.3 // 将堆栈顶部的引用弹出并存储到局部变量 d
IL_0022: ldstr "Print Word!" // 为字符串 "Print Word!" 分配内存,并推送其引用到堆栈
IL_0027: stloc.s e // 将堆栈顶部的引用弹出并存储到局部变量 e
从上面的CIL代码中可以看出,字符串(作为引用类型)的分配是在堆上进行的,但它们的引用(即指向堆上对象的指针)是存储在堆栈上的。这样,我们就可以通过引用快速访问堆上的对象,同时由CLR(公共语言运行时)负责垃圾回收,以确保不再使用的对象能够被及时清理。

综上所述,通过CIL观察.NET中值类型和引用类型的内存分配,我们可以更深入地理解.NET的内存管理机制。值类型直接在堆栈上分配,访问速度快但生命周期受限于栈帧;而引用类型则在堆上分配,通过引用访问,并由CLR负责垃圾回收。这种机制既保证了程序的性能,又简化了内存管理的复杂性。

相关文章
|
4月前
|
存储 开发框架 .NET
"揭秘.NET内存奥秘:从CIL深处窥探值类型与引用类型的生死较量,一场关于速度与空间的激情大戏!"
【8月更文挑战第16天】在.NET框架中,通过CIL(公共中间语言)可以深入了解值类型与引用类型的内存分配机制。值类型如`int`和`double`直接在方法调用堆栈上分配,访问迅速,生命周期随栈帧销毁而结束。引用类型如`string`在托管堆上分配,堆栈上仅存储引用,CLR负责垃圾回收,确保高效且自动化的内存管理。
56 6
|
2月前
|
Java 测试技术 Android开发
让星星⭐月亮告诉你,强软弱虚引用类型对象在内存足够和内存不足的情况下,面对System.gc()时,被回收情况如何?
本文介绍了Java中四种引用类型(强引用、软引用、弱引用、虚引用)的特点及行为,并通过示例代码展示了在内存充足和不足情况下这些引用类型的不同表现。文中提供了详细的测试方法和步骤,帮助理解不同引用类型在垃圾回收机制中的作用。测试环境为Eclipse + JDK1.8,需配置JVM运行参数以限制内存使用。
32 2
|
4月前
|
前端开发 JavaScript Java
揭开 JavaScript 垃圾回收的秘密——一场与内存泄漏的生死较量,让你的代码从此焕然一新!
【8月更文挑战第23天】本文通过多个实例深入探讨了JavaScript中的垃圾回收机制及其对应用性能的影响。首先介绍了基本的内存管理方式,随后分析了变量不再使用时的回收过程。接着,通过事件监听器未被移除及全局变量管理不当等场景展示了常见的内存泄漏问题。最后,文章介绍了使用`WeakRef`和`FinalizationRegistry`等现代API来有效避免内存泄漏的方法。理解并运用这些技术能显著提升Web应用的稳定性和效率。
92 0
|
3月前
|
开发框架 前端开发 JavaScript
ASP.NET MVC 教程
ASP.NET 是一个使用 HTML、CSS、JavaScript 和服务器脚本创建网页和网站的开发框架。
44 7
|
3月前
|
存储 开发框架 前端开发
ASP.NET MVC 迅速集成 SignalR
ASP.NET MVC 迅速集成 SignalR
66 0
|
4月前
|
开发框架 前端开发 .NET
ASP.NET MVC WebApi 接口返回 JOSN 日期格式化 date format
ASP.NET MVC WebApi 接口返回 JOSN 日期格式化 date format
50 0
|
4月前
|
开发框架 前端开发 安全
ASP.NET MVC 如何使用 Form Authentication?
ASP.NET MVC 如何使用 Form Authentication?
|
4月前
|
开发框架 .NET
Asp.Net Core 使用X.PagedList.Mvc.Core分页 & 搜索
Asp.Net Core 使用X.PagedList.Mvc.Core分页 & 搜索
135 0
|
7月前
|
开发框架 前端开发 .NET
ASP.NET CORE 3.1 MVC“指定的网络名不再可用\企图在不存在的网络连接上进行操作”的问题解决过程
ASP.NET CORE 3.1 MVC“指定的网络名不再可用\企图在不存在的网络连接上进行操作”的问题解决过程
195 0
|
7月前
|
开发框架 前端开发 JavaScript
JavaScript云LIS系统源码ASP.NET CORE 3.1 MVC + SQLserver + Redis医院实验室信息系统源码 医院云LIS系统源码
实验室信息系统(Laboratory Information System,缩写LIS)是一类用来处理实验室过程信息的软件,云LIS系统围绕临床,云LIS系统将与云HIS系统建立起高度的业务整合,以体现“以病人为中心”的设计理念,优化就诊流程,方便患者就医。
81 0