zoukankan      html  css  js  c++  java
  • C#学习笔记----栈与堆的知识

    http://my.oschina.net/lichaoqiang/blog/291906

    当我们对.NET Framework的一些基本面了解之后,实际上,还是很有必要了解一些更底层的知识。比如.NET Framework是如何进行内存管理的,是如何垃圾回收的......这样,我们才能写出更高性能的程序。

    在.NET Framework中,有2个地方帮我们保存管理数据:一个是"堆",也叫"托管堆",由.NET Framework的垃圾收集器(Garbage Collection, GC)管理;另一个是"栈",也叫"线程堆栈",由操作系统直接管理。它们都寄宿在操作系统内存。

    本篇主要包括:
    ■  什么是"栈"
    ■  什么是"堆"
    ■  值类型内存分配
        ※  在方法内的值类型内存分配
        ※  在引用类型内部的值类型内存分配
    ■  练习题   

      什么是"栈"

    可以把"栈"想像成由下而上堆叠起来的盒子,值类型实例存储于此。
    1

    在 应用程序中,每当调用一个方法,就相当于在"堆"上放上了一个盒子A,这时,应用程序只能使用处在"栈"最上方、刚被放上的这个盒子A,当方法执行结束, 相当于把最上方的盒子A扔掉。接下来,刚才还在A下面的盒子B就处在"栈"的最上方了,于是应用程序又开始使用盒子B,以此类推。而且,每当把最上面的盒 子扔掉,其对应的内存也被自动释放。

    栈的优点是执行效率高,缺点是存储容量有限。

    在.NET Framework中,所有派生于System.ValueType的就是值类型,值类型实例位于"栈"。值类型包括:
    ● bool
    ● byte
    ● char
    ● decimal
    ● double
    ● enum
    ● float
    ● int
    ● long
    ● sbyte
    ● short
    ● stuct
    ● uint
    ● ulong
    ● short

      什么是"堆"


    可以把"堆"想像成一些摆放无序的盒子,引用类型实例存储于此。
    2  

    我们可以在任何时候,使用任何盒子。我们需要借助垃圾收集器(Garbage Collection, GC)的自动回收机制或手动处理,以保证"堆"的盒子被及时回收。


    另 外,根据引用类型实例的大小,"堆"分为"GC堆"和"LOH(Large Object Heap)堆",当引用类型实例大小小于85000个字节的时候,实例被分配在"GC堆"上;当实例大小大于或等于于85000个字节的时候,实例被分配 在"LOH(Large Object Heap)堆"。

    在.NET Framework中,所有派生于System.Object的就是引用类型,引用类型实例位于"堆"。引用类型包括:
    ● 类 class
    ● 接口 interface
    ● 委托 delegate
    ● object
    ● string

      值类型内存分配

      在方法内的值类型内存分配

    public int Add(int x)
    {    int result;
        result = x + 2;    return result;
    }

    1、在执行Add(int x)方法之前,方法参数x被存放到"栈"的顶部。
    3

    2、在"method table"中搜寻Add()方法,如果找不到,就让JIT及时编译再存放到"method table"中去。

    3、开始执行Add(int x)方法,局部变量result也需要"栈"中的一些内存。
    4

    4、当方法执行完毕,先释放result,再释放x,线程堆栈指针重新指向。
    5

      在引用类型内部的值类型内存分配

    public class MyClass
    {    public int MyValue;
    }public MyClass Add(int x)
    {
        MyClass result = new MyClass();
        result.MyValue = x + 2;    return result;
    }

    复制代码

    1、在执行Add(int x)方法之前,方法参数x被存放到"栈"的顶部。
    3

    2、在"method table"中搜寻Add()方法,如果找不到,就让JIT及时编译再存放到"method table"中去。

    3、开始执行Add(int x)方法,执行MyClass result = new MyClass()
    先在托管堆上创建一个MyClass的实例,然后在栈上开辟一块空间并指向实例地址。
    6

    4、当方法执行完毕,在栈中由上到下依次释放内存。
    7

    此时,在托管堆上的MyClass实例如何处理呢?

    5、此时,垃圾回收器登场了,他在托管堆中搜寻那些不再被引用的对象实例,然后实施回收。

  • 相关阅读:
    FFT 和 NTT
    神秘构造题
    P4396 [AHOI2013]作业
    杜教筛学习笔记
    杜教筛
    「$mathcal{Darkbzoj}$」神犇和蒟蒻
    「CQOI2015」选数
    「$mathcal{Atcoder}$」$mathcal{ARC101}$
    「NOI2019」退役记???
    「李超线段树」
  • 原文地址:https://www.cnblogs.com/changrulin/p/5282773.html
Copyright © 2011-2022 走看看