腾讯面前端暑期实习还有一道让我有点窒息的题目,当时好像是问我C#内存分块底层?我有点不大懂面试官的意思。所以干脆一起总结一下免得无话可说。

1 Overview

首先开宗明义,C#是一种托管语言,它的垃圾回收机制(GC)是由.net平台负责的,加之C#语言并没有指针,所以我们在使用过程中极少会考虑到内存使用状况以及项目在运行过程中是如何进行内存管理的。但是,C#只是在内存管理方面对程序员隐藏了,并不代表它不涉及这些东西,甚至其内部内存管理或许比自己手动管理更加复杂。(我似乎明白为啥我对C#内存管理一无所知了

这里复习一下托管与非托管代码

托管代码CLR由运行环境执行的代码(非操作系统)可以自动获得语言运行库服务,自动垃圾回收,类型检查,安全等。

  • 不能直接访问内存,所以不使用指针(因为没有直接操作底层API,而是通过环境)(需要创建类库即DLL)

而非托管代码则与公共语言运行库无关,生成机器可以直接执行的二进制代码。

  • 可以使用指针直接读取内存

所以C#作为托管语言,是由运行环境负责执行的,自动垃圾回收类型检查安全等等。但是就像C++一样,C#内存也是分区域的,值类型,引用类型,指针,指令等等。

  • 值类型:常见的primitive type,比如int char
  • 引用类型:继承自System.Object,也就是对象,也包括String
  • 指针类型:在内存区中,指向一个类型的引用,通常被称为“指针”,它是受CLR( Common Language Runtime:公共语言运行时)管理,我们不能显式使用。指针在内存中(栈区)占一块内存区,它本身只代表一个内存地址(或者null),它所指向的另一块内存区(堆区)才是我们真正的数据或者类型。
  • 指令:这个就不说了,PC就是干这个的应该

2 内存分区

1) 栈区:由编译器自动分配释放 ,存放值类型的对象本身,引用类型的引用地址(指针),静态区对象的引用地址(指针),常量区对象的引用地址(指针)等。其操作方式类似于数据结构中的栈。

2) 堆区(托管堆):用于存放引用类型对象本身。在c#中由.net平台的垃圾回收机制(GC)管理。栈,堆都属于动态存储区,可以实现动态分配。

3) 静态区及常量区:用于存放静态类,静态成员(静态变量,静态方法),常量的对象本身。由于存在栈内的引用地址都在程序运行开始最先入栈,因此静态区和常量区内的对象的生命周期会持续到程序运行结束时,届时静态区内和常量区内对象才会被释放和回收(编译器自动释放)。所以应限制使用静态类,静态成员(静态变量,静态方法),常量,否则程序负荷高。

4) 代码区:存放函数体内的二进制代码。

3 内存分配

值类型肯定直接在栈上分配空间就行,没啥说的

引用类型(对象)在堆区分配空间,但是引用地址(指针)还是在栈区,通过引用地址去堆区内寻找对象本身的值。所以只有引用类型对象会涉及到深拷贝的问题,而值类型都是深拷贝,因为不存在指针,直接栈上就分配了。如果需要深拷贝或者浅拷贝对象请参考我的另一篇文章

json和Jason:C#的深拷贝浅拷贝​zhuanlan.zhihu.com

值得注意的是,静态变量应该是在你或者系统代码第一次访问这个类的时候,clr 会去加载这个类,当然也有其他说法比如说分情况:

  • 编译时已知数据,静态成员直接写入PE文件
  • 加载时可以决定的数据,程序加载时初始化。
  • 运行时才能决定的数据,调用type initialize

总的来说,静态变量生命周期大致是从程序加载到程序销毁,所以变量的指针存放在栈区,值本身存放在静态存储区。

4 内存管理

1) 栈区管理:

C#中栈是编译期间就分配好的内存空间,因此你的代码中必须就栈的大小有明确的定义;栈区内存无需我们管理,也不受GC管理,栈顶元素使用完毕弹出就会立即释放

2)堆区管理:

堆区是程序运行期间动态分配的内存空间,你可以根据程序的运行情况确定要分配的堆内存的大小。在C#中堆区内存由GC(Garbage collection:垃圾收集器)负责清理当对象超出作用域范围或者对象失去指向的引用地址,就会在一定时间内进行统一的处理,无需程序员手动处理。

当对象不再使用时,这个被存储在堆栈中的引用变量将被删除,但是从上述机制可以看出,在托管堆中这个引用指向的对象仍然存在,其空间何时被释放取决垃圾收集器而不是引用变量失去作用域时。

在使用电脑的过程中大家可能都有过这种经验:电脑用久了以后程序运行会变得越来越慢,其中一个重要原因就是系统中存在大量内存碎片,就是因为程序反复在堆栈中创建和释入变量,久而久之可用变量在内存中将不再是连续的内存空间,为了寻址这些变量也会增加系统开销。在.net中这种情形将得到很大改善,这是因为有了垃圾收集器的工作,垃圾收集器将会压缩托管堆的内存空间,保证可用变量在一个连续的内存空间内,同时将堆栈中引用变量中的地址改为新的地址,这将会带来额外的系统开销,但是,其带来的好处将会抵消这种影响,而另外一个好处是,程序员将不再花上大量的心思在内存泄露问题上。

垃圾收集器除了会压缩托管堆、更新引用地址、还会维护托管堆的信息列表。

以后我在整理一下页面置换的一些问题(复习OS

参考资料:

CSDN-专业IT技术社区-登录​blog.csdn.net

如何释放指针又不影响内存数据_C# 内存机制 - 基础篇相关推荐

  1. 数据包工具--Scapy基础篇

    数据包工具--Scapy基础篇 零.前言 一.Scapy是什么? 二.Scapy基础 1 利用pip安装库 2 基本使用 2.1 conf变量 2.2 lsc()方法 2.3 ls()方法 3 发送数 ...

  2. 0基础python入门书籍 excel_【曾贤志】从零基础开始用Python处理Excel数据 - 第1季 基础篇...

    =====[曾贤志]从零基础开始用Python处理Excel数据 第1季 基础篇====== 1-1 什么是python? .mp4 1-2 为什么要学习用Python处理Excel表格? .mp4 ...

  3. atomic 内存序_C++内存屏障(内存顺序)总结

    原子操作(atomic)是无锁编程(Lock-Free Programming)的基础.以往,要使用atomic操作,我们一般会使用gcc内置的原子操作接口,或者是基于指定平台硬件指令封装的atomi ...

  4. 大数据 - 文本文件数据提取工具之一 基础篇常见文本格式

    基础篇如何正确的拆分常见的文本格式, 什么样的字符能做拆分符号,理论上所有的字符都可以作为拆分符号用来拼接多列数据, 在拆分列数据的时候,数据里面不能再有这个拆分符号一样的字符串,否则数据就无法分开了 ...

  5. Java内存马攻防实战——攻击基础篇

    ​ 在红蓝对抗中,攻击方广泛应用webshell等技术在防守方提供的服务中植入后门,防守方也发展出各种技术来应对攻击,传统的落地型webshell很容易被攻击方检测和绞杀.而内存马技术则是通过在运行的 ...

  6. 大数据笔记30—Hadoop基础篇13(Hive优化及数据倾斜)

    Hive优化及数据倾斜 知识点01:回顾 知识点02:目标 知识点03:Hive函数:多行转多列 知识点04:Hive函数:多行转单列 知识点05:Hive函数:多列转多行 知识点06:Hive函数: ...

  7. 大数据笔记16—java基础篇12(JDBC 、连接池、事务)

    目录 JDBC jdbc概述 jdbc入门案例 API详解 jdbc工具类 预编译执行平台 1.SQL注入问题(安全问题) 2API详解:预处理对象(PreparedStatement) 使用连接池重 ...

  8. mongodb查询文件服务器的数据,服务器端知识库mongodb基础篇

    前言 对于nodejs而言,标配但数据库便是mongodb了.而我认为nodejs对于mongodb的操作最为便捷的插件之一就是mongoose,所有我们去掌握mongoose的基本配置就很有必要了, ...

  9. 大数据笔记9—java基础篇5(API)

    java_API API String类 创建字符串对象的区别对比 String字符串的特点 字符串的比较 例题(String) 例题1. 模拟登陆 例题2遍历字符串 例题3.案例 :统计字符次数 例 ...

最新文章

  1. 解决Mysql:unrecognized service错误的方法(CentOS)附:修改用户名密码
  2. 为什么RedisCluster会设计成16384个槽呢?
  3. oracle 序列号同步,关于序列同步的问题
  4. oracle存储过程生成单号,Oracle生成单据编号存储过程的实例代码
  5. python numpy使用
  6. CSS3学习系列之颜色
  7. IDT系列:(二)中断处理过程,使用bochs调试IDT中的中断服务程序
  8. Git(6)-Git配置文件、底层操作命令
  9. java泛型实例化_java基础-泛型举例详解
  10. STM32通过IIC驱动MLX90614红外温度传感器
  11. 你了解Android中的Activity吗?
  12. html2canvas.js 截屏微信头像不显示
  13. 我所知道查找算法之斐波拉契(黄金分割法)查找
  14. HTTP tunneling is disabled问题 解决
  15. 稍微好看点的登录页面html
  16. 【Git】fatal Not a git repository or any of the parent direc
  17. 【数据库运维】mysql备份恢复练习
  18. 重启随机游走(RWR)算法
  19. 【MySQL】检索数据
  20. 【Linux】LVM的创建及使用

热门文章

  1. MATLAB利用YCBCR切割出人脸头像
  2. MATLAB_图形学_形态学课程_找出薛之谦的歌词所有字数
  3. 防火墙产品原理与应用:防火墙产品的技术及实现关于IPV6【寒假】
  4. 机器学习中Bagging和Boosting的区别
  5. 值得一看的文本检测方法
  6. 单张图像重建3D人手、人脸和人体
  7. 假如计算机是中国人发明的,那代码应该这么写
  8. 无屏幕和键盘配置树莓派WiFi和SSH
  9. Silverlight实用窍门系列:52.Silverlight中的MVVM框架极速入门(以MVVM Light Toolkit为例)...
  10. MySQL 关于毫秒和微秒的处理,MySQL获取毫秒!