前言:我们经常听到一个概念,堆和栈。实际上,数据结构中有两个相同的概念,但这与内存堆栈不同。本文还将说明它们之间的区别,此内。函数完成后,这些内容将被自动销毁。 。它的特点是效率高,但内存大小有限。
(4)堆区域--------由malloc和calloc分配的内存区域,其生命周期由free确定。堆的内存大小由程序员分配,理论上可以占据系统的所有内存。
这四个类别如下:
个人喜好,对这四个类别有更好的了解。请注意.bss .data在这里的含义。
摘要:
1. 5函数调用存储在堆栈存储器中后的返回地址
调用该函数时,将使用指向该函数的指针来指向该函数。函数返回时,它将返回到调用位置,该位置是函数调用结束后的返回地址。
此外,返回地址存储在堆栈中。首先调用的函数首先放在堆栈上,然后最后弹出,然后最后调用的函数放在堆栈上,然后首先弹出。
二、关于内存堆栈(内存堆栈)
2. 1堆栈溢出
程序自动将“堆栈”分配并回收给操作系统。它既快速又易于使用,但是不能由程序员控制。但是堆栈空间很小。只要堆栈的剩余空间大于请求的空间,系统就会为程序提供内存。如果要分配的空间大于堆栈内存,分配将失败并提示堆栈溢出错误。
#include int main()
{
int i = 10; //变量i储存在栈区中
const int i2 = 20; //const局部变量也存储在stack
int i3 = 30;
std::cout << &i << " " << &i2 << " " << &i3 << std::endl;
return 0;
}
/*运行结果为:
0x28fedc 0x28fed8 0x28fed4 16进制地址,递减的
*/
注意:const局部变量也存储在堆栈区域中,并且堆栈区域沿地址递减的方向增长。
2. 2堆栈的特征
([1)应用程序大小限制
在Windows下,堆栈是一个扩展到低位地址的数据结构,是内存的连续区域。这句话意味着系统顶部将确定堆栈顶部的地址和堆栈的最大容量。在Windows下,堆栈的大小为2M(有人说是1M,简而言之,这是在编译时确定的常数),如果当请求的空间超过堆栈的剩余空间时,将提示溢出。因此,堆栈中可用的空间较小。
([2) Stack应用程序的效率很高
系统自动分配堆栈,速度更快。但是程序员没有控制权,结束后它将由操作系统释放。
([3)堆栈使用过程
当堆栈处于函数调用中时,
此函数调用结束时,局部变量首先从堆栈中弹出,然后是参数,最后是堆栈顶部的指针指向最初存储的地址,这是存储区中的下一条指令。主要功能,此后程序将继续运行。
三、关于内存堆(内存堆)
3. 1堆溢出
堆是一个扩展到更高地址的数据结构,并且是一个不连续的存储区域。这是因为系统使用链表存储空闲内存地址,这自然是不连续的。链表的遍历方法是从低地址到高地址,并且堆的大小受计算机系统中有效内存的限制。可以看出,堆获得的空间相对灵活,相对较大。
程序员向操作系统申请一块内存。当系统收到该程序的应用程序时,它将遍历记录空闲内存地址的链表,找到第一个空间大于请求空间的堆节点,然后从空闲节点列表中删除该节点。 ,并将节点的空间分配给程序。分配速度慢,地址不连续,并且很容易碎片化。另外,应用程序是由程序员编写的,程序员也必须负责破坏程序,否则会导致内存泄漏。
3. 2堆特征
操作系统具有一个链接列表,该列表记录了可用内存地址。当系统收到程序的应用程序时,它将遍历链接列表以查找其空间大于请求的空间的第一个堆节点,然后从可用空间中选择该节点。从链接列表中删除,然后将节点的空间分配给程序。另外,对于大多数系统而言,此分配的大小将记录在此内存空间的第一个地址,这样代码中的delete语句就可以正确释放此内存空间。另外,由于找到的堆节点的大小可能与应用程序的大小不完全相同,因此系统会自动将多余的部分放入空闲列表中。
([1)应用程序大小限制
堆是一个扩展到更高地址的数据结构,并且是一个不连续的存储区域。这是因为系统使用链表存储自然不连续的空闲内存地址,并且链表的遍历方向是从低地址到高地址。堆的大小受计算机系统中可用物理内存的限制。可以看出,堆获得的空间更加灵活,更大。
([2)堆使用效率
堆是new分配的内存,通常速度较慢并且容易出现内存碎片,但是使用起来最方便。
([3)堆使用的过程
堆:通常,一个字节用于在堆的开头存储堆的大小。堆中的特定内容由程序员安排。
摘要:
堆栈内存:从高地址到低地址,连续,快速,小空间;
堆栈内存:从低地址到高地址,不连续,缓慢且空间大。
可以列为下表:
如何申请
内存大小
使用效率
存储内容
堆栈(堆栈)
自动发布应用程序
小
高效
堆(堆)
手动申请发布
大
慢
四、为什么C和C ++在传递数组时传递地址或引用?
从上面的分析中我们可以知道,由于该函数的参数存储在堆栈存储器中,所以如果一个数组比较大,我就传递一个大数组。如果将数组的值复制到形式参数,将不可避免地导致堆栈内存不足,即“堆栈溢出”,因此可以通过仅传递地址值而不传递实际值来避免此问题。 。实际上,诸如Java和C#之类的语言也具有相同的基本原理,这将在后面解释。
摘要:
C语言中函数的参数传递通常分为值传递/指针传递
在C#,Java和C ++中,函数的参数传递通常分为值传递/引用传递
实际上,从内存“堆栈存储器”的角度来看,所有函数参数的传递只有一种形式,即值传递。
因为参数是一个值,所以堆栈中的值将被复制到函数的形式参数中,这当然是值传递,
如果参数是地址或引用,它还将在堆栈区域中复制该地址或将引用传递给函数参数,但是此地址或引用不是真实数据,复制的地址相同或引用的任何人将指向同一条数据,因此我们称其为传递的引用或地址。
简而言之:传递地址或引用只是表面的,本质是“按值传递”。
个人理解,如果伟大的上帝有更好的理解,我希望与大家分享和交流,谢谢。如果您想彻底理解这些概念,可以将几篇文章结合起来阅读,以更好地理解它们。
五、 C#内存管理
有关详细信息,请参阅我的另一篇文章:
在一篇文章中了解C#的堆,栈,值类型,引用类型
C#(CLR)中的内存分配分析
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/shoujiruanjian/article-373658-1.html