您的位置:首页 > 其它

堆,栈和GC的个人理解

2020-04-02 08:03 337 查看

int 类型是值类型,值类型保存在栈里面,栈是先进后出
而object是引用类型,里面的值保存在堆里面,而引用名在栈里面
然后所有的引用类型都保存在堆里面,而值类型如果被引用类型包住,比如引用类型的方法,里面的值,就会保存在堆里面,而没有包住,或者new,则会在栈里面,new的话,是因为是编译时新建的,所以出现在栈里面
为什么栈要先进后出呢?比如先定义一个int A,然后int B=A,此时如果要删除,就是从后往前删,肯定要先删B,再删A,不然就会出错,这就是先进后出的原因
然后拆箱装箱是什么呢,就是把一个值类型给引用类型,引用类型再给值类型,就是把值放进堆这个箱子里面,然后再从堆这个箱子取出到栈里面.拆箱和装箱会造成一定的性能损耗,一般是父子类才会发生这种情况

int a=1;
object o=i;
int b=(int)o;

而一个引用类型如果把值等于另一个引用类型,而且原来的值没有其他引用的话,就会变成垃圾,需要回收,而回收就需要GC了

GC

GC是c#的回收机制,是在内存不够用的情况下,回收内存中的托管资源,来节省内存,而非托管资源则是需要手动回收
托管资源是什么呢?就是堆里面的东西,而非托管资源呢,则是外面的,比如数据库,excel表,txt文件,这些就没办法了,只能手动的,比如SqlConnection的Dispose手动结束
不过现在可以用using来自动回收,不必手动回收了.
然后回收的东西,则是垃圾,而垃圾就是完全访问不到的东西
比如定义一个引用类型,然后让这个引用类型等于另一个,那么原来那个引用的东西就已经访问不到了,或者在一个代码块里面,结束这个代码块了,里面的东西也自然清空了,不然不同的方法,同名的变量,不就冲突了吗,所以结束就自动删除,但是堆里面东西还在,就要清除
而清除的时间是不定的,并且清除的时候,会阻塞所有线程,不然清除的时候加一个,咋清除啊
然后清除的顺序,清除是首先把所有东西标记为0,然后清除之后,就会把余下的标记为1级,下次再回收的时候,首先从0开始,然后清除到1,再把1的标记为2
好了,说完原理后,就来说说是怎么回收的,首先嘛,肯定是检测是否手动调用了回收方法Dispose,这个方法很多托管资源都有,如果调用了的话,就回收,并且阻止析构函数的调用
然后这个析构函数又是什么呢?这个析构函数是防止忘记手动调用而自动用的,不过也不能过度依赖,万一出问题呢?所以还是手动用Dispose吧,不过现在封装的很好了,比如,using(SqlConnection conn=new
SqlConnection())就会在结束后自动调用Dispose,然后析构函数是什么呢?
析构函数用于释放被占用的系统资源
析构函数的名字由符号“~”加类名组成,比如类名A,析构函数就是~A。
使用析构函数时,应该注意下面的问题:
只能在类中使用析构函数,不能在结构中使用析构函数。
一个类只能有一个析构函数
不能继承或重载析构函数
析构函数只能被自动调用
析构函数没有任何修饰符、没有任何参数、也不返回任何值

内存泄漏

然后还有一点就是内存泄漏,这个问题很少出现的,一般都是计算机给程序分配的内存小于程序需要的,有2种情况
1,程序问题.比如我定义了大量静态参数,又无法回收,然后就会出现这种情况
2,电脑问题,同时多个程序跑,然后内存小,就这样了
最后就是关闭程序的时候,这个时候就不是回收了,而是程序退出,不过也会一次GC
.

  • 点赞
  • 收藏
  • 分享
  • 文章举报
漫漫长路,慢慢走 发布了12 篇原创文章 · 获赞 2 · 访问量 232 私信 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: