堆与栈
- 格式:doc
- 大小:15.00 KB
- 文档页数:2
栈和堆的区别 (转) 终于知道区别了(2007-09-12 08:50:49)转载标签:IT/科技一个由 c/C++ 编译的程序占用的内存分为以下几个部分:1 、栈区( stack )—由编译器自动分配释放,存放函数的参数值,局部变量的值等。
其操作方式类似于数据结构中的栈。
2 、堆区( heap )—一般由程序员分配释放,若程序员不释放,程序结束时可能由 OS 回收。
注意它与数据结构中的堆是两回事,分配方式倒是类似于链表,呵呵。
3 、全局区(静态区)( static )—全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。
程序结束后由有系统释放。
4 、文字常量区—常量字符串就是放在这里的。
程序结束后由系统释放。
5 、程序代码区—存放函数体的二进制代码。
例子程序:这是一个前辈写的,非常详细//main.cppint a = 0; //全局初始化区char *p1; //全局未初始化区main(){int b; 栈char s[] = "abc"; //栈char *p2; //栈char *p3 = "123456"; //123456在常量区,p3在栈上。
static int c =0; //全局(静态)初始化区p1 = (char *)malloc(10);p2 = (char *)malloc(20); //分配得来得10和20字节的区域就在堆区。
strcpy(p1, "123456"); //123456放在常量区,编译器可能会将它与p3所指向的"123456"优化成一个地方。
}栈:在 Windows 下,栈是向低地址扩展的数据结构,是一块连续的内存的区域。
这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,在 WINDOWS 下,栈的大小是 2M (也有的说是 1M ,总之是一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时,将提示 overflow 。
尽管在.NET framework下我们并不需要担心内存管理和垃圾回收(Garbage Collection),但是我们还是应该了解它们,以优化我们的应用程序。
同时,还需要具备一些基础的内存管理工作机制的知识,这样能够有助于解释我们日常程序编写中的变量的行为。
在本文中我将讲解栈和堆的基本知识,变量类型以及为什么一些变量能够按照它们自己的方式工作。
在.NET framework环境下,当我们的代码执行时,内存中尽管在.NET framework下我们并不需要担心内存管理和垃圾回收(Garbage Collection),但是我们还是应该了解它们,以优化我们的应用程序。
同时,还需要具备一些基础的内存管理工作机制的知识,这样能够有助于解释我们日常程序编写中的变量的行为。
在本文中我将讲解栈和堆的基本知识,变量类型以及为什么一些变量能够按照它们自己的方式工作。
在.NET framework环境下,当我们的代码执行时,内存中有两个地方用来存储这些代码。
假如你不曾了解,那就让我来给你介绍栈(Stack)和堆(Heap)。
栈和堆都用来帮助我们运行代码的,它们驻留在机器内存中,且包含所有代码执行所需要的信息。
* 栈vs堆:有什么不同?栈负责保存我们的代码执行(或调用)路径,而堆则负责保存对象(或者说数据,接下来将谈到很多关于堆的问题)的路径。
可以将栈想象成一堆从顶向下堆叠的盒子。
当每调用一次方法时,我们将应用程序中所要发生的事情记录在栈顶的一个盒子中,而我们每次只能够使用栈顶的那个盒子。
当我们栈顶的盒子被使用完之后,或者说方法执行完毕之后,我们将抛开这个盒子然后继续使用栈顶上的新盒子。
堆的工作原理比较相似,但大多数时候堆用作保存信息而非保存执行路径,因此堆能够在任意时间被访问。
与栈相比堆没有任何访问限制,堆就像床上的旧衣服,我们并没有花时间去整理,那是因为可以随时找到一件我们需要的衣服,而栈就像储物柜里堆叠的鞋盒,我们只能从最顶层的盒子开始取,直到发现那只合适的。
为什么栈地址从⾼到低⽣长,堆从低到⾼
这个问题与虚拟地址空间的分配规则有关,每⼀个可执⾏C程序,从低地址到⾼地址依次是:text,data,bss,堆,栈,环境参数变量;其中堆和栈之间有很⼤的地址空间空闲着,在需要分配空间的时候,堆向上涨,栈往下涨。
这样设计可以使得堆和栈能够充分利⽤空闲的地址空间。
如果栈向上涨的话,我们就必须得指定栈和堆的⼀个严格分界线,但这个分界线怎么确定呢?平均分?但是有的程序使⽤的堆空间⽐较多,⽽有的程序使⽤的栈空间⽐较多。
所以就可能出现这种情况:⼀个程序因为栈溢出⽽崩溃的时候,其实它还有⼤量闲置的堆空间呢,但是我们却⽆法使⽤这些闲置的堆空间。
所以呢,最好的办法就是让堆和栈⼀个向上涨,⼀个向下涨,这样它们就可以最⼤程度地共⽤这块剩余的地址空间,达到利⽤率的最⼤化!!。
在计算机领域,堆栈是一个不容忽视的概念,但是很多人甚至是计算机专业的人也没有明确堆栈其实是两种数据结构。
堆栈都是一种数据项按序排列的数据结构,只能在一端(称为栈顶(top))对数据项进行插入和删除。
要点:堆:顺序随意栈:后进先出(Last-In/First-Out)编辑本段堆和栈的区别一、预备知识—程序的内存分配一个由c/C++编译的程序占用的内存分为以下几个部分1、栈区(stack)—由编译器自动分配释放,存放函数的参数值,局部变量的值等。
其操作方式类似于数据结构中的栈。
2、堆区(heap)—一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收。
注意它与数据结构中的堆是两回事,分配方式倒是类似于链表。
3、全局区(静态区)(static)—,全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。
- 程序结束后由系统释放。
4、文字常量区—常量字符串就是放在这里的。
程序结束后由系统释放。
5、程序代码区—存放函数体的二进制代码。
二、例子程序这是一个前辈写的,非常详细//main.cppint a = 0; 全局初始化区char *p1; 全局未初始化区main(){int b; 栈char s[] = "abc"; 栈char *p2; 栈char *p3 = "123456"; 123456\0在常量区,p3在栈上。
static int c =0;全局(静态)初始化区p1 = (char *)malloc(10);p2 = (char *)malloc(20);}分配得来得10和20字节的区域就在堆区。
strcpy(p1, "123456"); 123456\0放在常量区,编译器可能会将它与p3所指向的"123456"优化成一个地方。
堆和栈,malloc分配的空间是堆,局部变量都在栈中堆和栈的区别⼀个由C/C++编译的程序占⽤的内存分为以下⼏个部分1、栈区(stack)— 由编译器⾃动分配释放,存放函数的参数值,局部变量的值等。
其操作⽅式类似于数据结构中的栈。
2、堆区(heap) — ⼀般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收。
注意它与数据结构中的堆是两回事,分配⽅式倒是类似于链表,呵呵。
3、全局区(静态区)(static)—,全局变量和静态变量的存储是放在⼀块的,初始化的全局变量和静态变量在⼀块区域,未初始化的全局变量和未初始化的静态变量在相邻的另⼀块区域。
- 程序结束后由系统释放。
4、⽂字常量区 —常量字符串就是放在这⾥的。
程序结束后由系统释放5、程序代码区—存放函数体的⼆进制代码。
例⼦:#include <stdio.h>int a = 0; 全局初始化区char *p1; 全局未初始化区main(){ int b; 栈 char s[] = "abc"; 栈 char *p2; 栈 char *p3 = "123456"; 123456\0在常量区,p3在栈上。
static int c =0;全局(静态)初始化区 p1 = (char *)malloc(10); p2 = (char *)malloc(20); //分配得来得10和20字节的区域就在堆区。
strcpy(p1, "123456"); //123456\0放在常量区,编译器可能会将它与p3所指向的"123456"优化成⼀个地⽅。
}。
栈内存和堆内存的理解
栈内存和堆内存是操作系统管理内存的典型结构,是用于与运行程序有关的内存管理中的基本概念,它们共同构成了操作系统管理内存的整体框架,提供了程序员运行程序的基本手段,也是计算机的核心技术之一.
栈内存是一种内存组织形式,主要存放函数及函数内所有变量的值,也用来存储函数调用时的位置指针和函数参数等信息,一般认为其操作迅速而浪费空间,是一种受限的通用缓存,主要适用于处理中断和递归调用等情况.
堆内存是由操作系统自动维护管理的一种大型内存,它被用于动态分配和管理大规模的内存,主要用于存放局部变量和全局变量,而这些变量的大小或者位置随着程序运行的不同而变化。
堆内存对外观不可见,它可以灵活地添加和释放。
因此,堆内存大小不受限制,是一种更有效率的内存管理。
总结一下,栈内存特性是快速,有限,专用内存,主要用于存放函数及函数内所有变量的值,而堆内存特性是浪费资源,灵活动态分配,可以存放局部变量和全局变量,而大小和位置由程序运行而变化。
如果要根据特性选择内存,则栈内存适用并发处理、处理函数调用等特殊应用,而堆内存适合动态分配大量内存的情况。
队列,栈,堆栈,数组,链表特点与区别1. 队列可以看成是有2个口的集合一个口叫队头一个叫队尾,只能在对头进行删除操作,在队尾做插入。
根据这样的操作。
队列特点是先进先出2.堆栈可以看成是有1个口的集合,这个口叫栈顶。
插入和删除操作只能在栈顶操作。
根据这样的操作。
堆栈的特点是是后进先出.3.链表是一种存储方式,它可以在非连续的内存空间里面存储一个集合的元素。
4.和它对应的是数组,数组要在连续的空间里存储集合的元素队列、栈是线性数据结构的典型代表,而数组、链表是常用的两种数据存储结构;队列和栈均可以用数组或链表的存储方式实现它的功能数组与链表:数组属于顺序存储中,由于每个元素的存储位置都可以通过简单计算得到,所以访问元素的时间都相同(直接访问数组下标);链表属于数据的链接存储,由于每个元素的存储位置是保存在它的前驱或后继结点中的,所以只有当访问到其前驱结点或后继结点后才能够按指针访问到自己,访问任一元素的时间与该元素结点在链接存储中的位置有关。
链表和数组是常用的两种数据存储结构,都能用来保存特定类型的数据。
1.占用的内存空间链表存放的内存空间可以是连续的,也可以是不连续的,数组则是连续的一段内存空间。
一般情况下存放相同多的数据数组占用较小的内存,而链表还需要存放其前驱和后继的空间。
2.长度的可变性链表的长度是按实际需要可以伸缩的,而数组的长度是在定义时要给定的,如果存放的数据个数超过了数组的初始大小,则会出现溢出现象。
3.对数据的访问链表方便数据的移动而访问数据比较麻烦;数组访问数据很快捷而移动数据比较麻烦。
链表和数组的差异决定了它们的不同使用场景,如果需要很多对数据的访问,则适合使用数组;如果需要对数据进行很多移位操作,则设和使用链表。
堆和栈有什么区别:1. 栈具有数据结构中栈的特点,后进先出,所有存放在它里面的数据都是生命周期很明确(当然要求它不能存放太久,占有的空间确定而且占用空间小),能够快速反应的!所有在Java中它存放的是8个基本数据类型和引用变量的,用完就马上销毁2.堆可以理解它就是个一个可大可小,任你分配的听话的内存操作单元;因此它的特点就是动态的分配内存,适合存放大的数据量!比如一个对象的所有信息,虽然它的引用指向栈中的某个引用变量;所有Java中堆是存放new 出来的对象的。
堆的名词解释堆,在我们的生活中随处可见,可以是由物体堆叠而成的一座山,也可以是由物品堆积而成的一摞书。
然而,在计算机科学领域里,堆又有着特定的含义和用途。
本文将从计算机的角度上解释堆的含义、用途及其相关概念。
一、堆的定义和概念在计算机科学中,堆(Heap)是一种特殊的数据结构,用于动态地存储和管理数据。
它通常是一个动态分配的内存空间,用于存储各种数据类型的对象,如整数、浮点数、字符串、对象等。
与栈不同,堆是由程序员自己管理的,需要手动分配和释放内存。
二、堆的用途在计算机编程中,堆的主要用途是存储和管理动态分配的数据。
它常常用于以下场景:1. 动态内存分配:堆可以根据程序的需要动态地分配内存空间,从而灵活地管理和使用内存资源。
2. 数据结构实现:堆可以作为其他高级数据结构的基础,如树、图等。
通过堆,我们可以更高效地实现各种数据结构操作,如查找、插入、删除等。
3. 程序运行时状态存储:堆可以用于存储程序在运行过程中需要保留和操作的数据,如动态数组、对象等。
三、堆的特点堆具有以下几个特点:1. 动态分配:堆是动态分配的内存空间,程序员可以根据需要分配和释放内存,灵活地管理数据和资源。
2. 随机访问:堆中的数据可以根据地址进行随机访问,而不需要遵循严格的顺序。
3. 存储复杂结构:堆不仅可以存储简单的数据类型,还可以存储复杂的数据结构,如对象、链表等。
4. 独立分配:堆的分配和释放不会影响其他数据区域的使用,相互独立。
四、堆的操作和实现在编程中,我们通过以下几个操作来管理堆的数据:1. 分配内存:使用动态内存分配函数(如malloc、new)来在堆上分配一块指定大小的内存空间。
2. 释放内存:使用内存释放函数(如free、delete)来释放之前分配的内存空间,避免内存泄漏。
3. 增加元素:向堆中添加新的元素,可以根据特定的算法来维护堆的结构和特性。
4. 删除元素:从堆中移除某个元素,同样需要经过特定的算法来维护堆的特性。
栈是由编译器在需要的时分配的,不需要时自动清除的变量存储区。
里面的变量通常是局部变量、函数参数等。
堆是有malloc()函数(C++语言为new运算符)分配为内存快,内存的释放由程序员手动控制,在C语言为free()完成(C++中为deleted)。
堆和栈的主要区别有以下几点:
(1)管理方式不同
栈编译器自动管理,无需程序员手工控制;而堆空间的申请释放工作由程序员控制,容易产生内存泄漏。
(2)空间的大小不同
栈是向低地址扩展的数据结构,是一块连续的内存区域。
这句话的意思是栈顶的地址和栈的最大容量是系统预先设定好,当申请的空间超过栈的剩余空间时,将提示溢出。
因此,用户能从栈获得空间较小。
堆是向高地址扩展的数据结构,是不连续的内存区域。
因为系统是用链表来存储空闲内存地址的,且链表的遍历方向是由低地址向高地址。
由此可见,堆获得空间较灵活,也较大。
栈中元素都是一一对应的,不会存在一个内存块从中弹出的情况。
(3)是否产生碎片
对于栈来讲,频繁的malloc/free(new/delete)势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低(虽然程序在退出后操作系统会对内存进行回收管理)。
对于栈来讲,则不会存在这个问题。
(4) 增长方向不同
堆的增长方向是向上的,即向着内存地址增加的方向。
栈的增长方向是向下的,即向着内存地址减小的方向。
(5)分配方式不同
堆都是程序中由malloc()函数动态申请分配并由free()函数释放的;栈的分配和释放是由编译器完成的,栈的动态分配由alloca()函数完成,但是栈的动态分配和对不同,它的动态分配是由编译器进行申请和释放的,无需手工实现。
(6)分配效率不同
栈是由机器系统提供的数据结构,计算机会在底层对栈提供支持;分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令进行。
堆则是C函数库提供的,它的机制很复杂,例如为了分配一块内存,库函数会按照一定的算法(具体的算法可以参考数据结构/操作系统)在堆内存中搜索可用的足够大的空间,如果没有足够大的空间(可能是由于内存碎片太多),就需要操作系统来重新整理内存空间,这样就有机会分到足够大小的内存,然后返回。
显然堆的效率要比栈低得多。
可执行代码运行时内存结构结构:
(1)代码区(text segment)。
代码区指令根据程序设计流程依次执行,对于顺序指令,则只会执行一次(每个进程),如果反复,则需要使用跳转指令,如果进行递归,则需要借助栈来实现。
代码区的指令包括操作码和要操作的对象(或对象地址引用)。
如果是里技术(及具体的数值),将直接包含在代码中;如果是局部变量,将在栈区分配空间。
然后引用该数的地址;如果是BSS去和数据区,在代码中同样是引用该数的地址。
(2)全局初始化数据区/静态数据区(Data Segment)。
只初始化一次。
(3)未初始化数据区(BBS)。
在运行时改变其值,存入的全局未初始化变量。
例如一个不在任何函数内的声明:long sum[1000];
(4)栈区(stack)。
由编译器自动分配释放,存放函数的参数值、局部变量的值等。
其操作方式类似于数据结构中的栈。
每当一个函数被调用,该函数返回地址和一些关于调用的信息,比如某些寄存器的内容改变,被存储对哦栈区。
然后这个被调用的函数再为它的自动变量和临时变量在栈区上分配空间,这就是C 实现递归函数的方法。
每执行依次函数递归函数调用,一个新的栈框架就会被使用,这样这个新实例栈里的变量就不会和该函数的另一个实例栈里面的变量混淆。
(5)堆区(heap)用于动态内存分配。
堆在内存中位于bss区和栈区之间。
一般由程序员分配和释放,若程序员不释放,结束程序时有可能由OS回收。
可执行代码存储结构
可执行代码在存储时分为代码区(text),数据区(data)和未初始化数据区(bss)。