栈
在C#中,每个线程都有自己的栈空间,栈空间的大小取决于操作系统和编译器的限制。一般来说,32位操作系统的栈空间大小约为1MB到4MB,64位操作系统的栈空间大小通常更大一些,大约在1MB到8MB之间。
栈:只要栈的剩余空间大于所申请空间,系统将为程序提供内存,否则将报异常提示栈溢出。
栈溢出异常
原因一个是临时变量过多,另外一个是死循环。
堆
堆:首先应该知道操作系统有一个记录空闲内存地址的链表,当系统收到程序的申请时,
会遍历该链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表
中删除,并将该结点的空间分配给程序。
另外,对于大多数系统,会在这块内存空间中的首地址处记录本次分配的大小,这样,代码中的delete
语句才能正确的释放本内存空间。
另外,由于找到的堆结点的大小不一定正好等于申请的大小,系统会自动的将多余的那部
分重新放入空闲链表中。
区别
堆(heap)和栈(stack)是计算机内存中两种不同的内存分配方式,它们有以下主要区别:
分配方式:
- 栈:栈是一种自动分配和释放内存的数据结构,存储在栈中的数据是按照后进先出(LIFO)的顺序存储和访问的。当你定义一个变量时,它会自动分配内存并且在该变量的作用域结束时自动释放内存。
- 堆:堆是一种动态分配和释放内存的数据结构,它允许你在运行时分配和释放内存。堆中的数据是无序存储的,并且需要手动管理内存的分配和释放。
分配速度:
- 栈:栈上的内存分配和释放是非常快速的,因为它是在编译时静态分配的。
- 堆:堆上的内存分配和释放相对较慢,因为它是在运行时动态分配的。
内存管理:
- 栈:栈上的内存分配和释放是由编译器自动管理的,无需手动干预。变量的生命周期与其作用域相对应,当变量离开作用域时,其所占用的内存会自动被释放。
- 堆:堆上的内存分配和释放需要显式地进行管理。在动态分配内存时,需要手动调用
new
操作符来分配内存,并且在不需要使用内存时,需要手动调用delete
操作符来释放内存,否则会导致内存泄漏。
内存分配方式:
- 栈:栈上的内存分配是连续的,以固定的大小分配内存。栈的大小在程序启动时就确定了,因此栈的大小是固定的。
- 堆:堆上的内存分配是不连续的,内存的分配和释放顺序是不确定的。堆的大小在程序运行时是动态变化的,取决于当前系统的可用内存大小。
总的来说
栈主要用于存储局部变量和函数调用的上下文信息,它的内存分配和释放由编译器自动管理
堆主要用于存储动态分配的内存和对象,需要手动管理内存的分配和释放,具有更大的灵活性和更高的开销。