堆(heap)与栈(stack)是程序存储空间上的一组概念。 应用程序启动时 程序启动时,windows的PE装载器会将PE文件(可执行文件,Unix/Linux 上是ELF)的不同部分的内容装入不同的内存区域。 程序的数据段包括.data段(全局变量)和.rdata段(静态变量和常量)。而PE装载器只能从程序中读出已初始化的全局变量和静态变量,并将它们放在的一段专门的初始化的数据的内存区域上。而未初始化的全局变量和静态变量则存放在一段专门的非初始化数据段的内存区域上开辟空间,并且都被初始化为0。这二者合在一起被称为data area。 程序的正文段(可再入程序,即可被多个进程共享的一串指令,是只读的)则是被装载器装入到被称为code area内存区域。 程序中任何需要动态分配内存的变量(如使用malloc/free或new/delete)的内存分配是在堆进行。而局部变量与自动变量的内存分配是在栈进行。 堆、栈 堆空间的内存分配属于用户级的内存分配,所分配的内存需要手动释放,否则会造成内存泄漏。当然,在应用程序销毁时,也能得到释放。在32位的系统中堆得大小可达4G,可见堆得空间可以很大。但是堆的频繁分配与释放可能会带来内存碎片,也可能会造成内核模式和用户模式(Unix/Linux 的内核态和用户态)频繁切换和申请内存,带来性能上的损失。例如可能会为了分配一块内存,C/C++库函数会按照一定的算法在堆内存中搜索,看是否有可用的足够大小的空间。如果没有足够大小的空间(可能是由于内存碎片太多),就有可能通过执行系统调用去增加程序数据段的内存空间,这样就有机会分到足够大小的内存,然后再返回。但是,我们要看到堆为我们提供了足够的对内存使用的灵活性。特别是在某些时候,动态地分配内存能为我们大大的节约内存空间。 栈空间的内存分配则由系统负责管理的,是系统级的内存分配,一般不需要我们手动的控制。局部变量、以及被调用的子程序的返回地址以及寄存器信息都存放在栈中。我们知道栈是FIFO(先进先出)的结构,因而栈空间上的内存始终是连续占用的,不会出现内存碎片。然而,栈的大小是有限制的。 例如,在VC6下面,默认的栈空间大小是1M。当然,可以修改: 打开工程,依次操作菜单如下:Project->Setting->Link,在Category 中选中Output,然后在Reserve中设定堆栈的最大值和commit。 堆与栈 堆与栈是两个不同的概念,但是我们习惯上却经常说“堆栈”这个词,这造成了许多的误会。因此,我们还要了解堆与栈的联系与区别。 首先,我们用一张图来直观的说明堆、栈在内存上的位置关系。
堆空间、栈空间和堆栈平衡
最新推荐文章于 2022-09-07 21:50:11 发布