`
isiqi
  • 浏览: 16482295 次
  • 性别: Icon_minigender_1
  • 来自: 济南
社区版块
存档分类
最新评论

堆空间、栈空间和堆栈平衡

阅读更多

堆和栈的区别
一、预备知识—程序的内存分配
一个由c/C++编译的程序占用的内存分为以下几个部分
1、栈区(stack)—由编译器自动分配释放,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
2、堆区(heap)—一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表,呵呵。
3、全局区(静态区)(static)—,全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。-程序结束后有系统释放
4、文字常量区—常量字符串就是放在这里的。程序结束后由系统释放
5、程序代码区—存放函数体的二进制代码。

申请后系统的响应
栈:只要栈的剩余空间大于所申请空间,系统将为程序提供内存,否则将报异常提示栈溢出。
堆:首先应该知道操作系统有一个记录空闲内存地址的链表,当系统收到程序的申请时,
会 遍历该链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表中删除,并将该结点的空间分配给程序,另外,对于大多数系统,会在这块内 存空间中的首地址处记录本次分配的大小,这样,代码中的delete语句才能正确的释放本内存空间。另外,由于找到的堆结点的大小不一定正好等于申请的大 小,系统会自动的将多余的那部分重新放入空闲链表中。

2.3申请大小的限制
栈:在Windows下,栈是向低地址扩展的数据结 构,是一块连续的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,在WINDOWS下,栈的大小是2M(也有的说是1M,总之是 一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时,将提示overflow。因此,能从栈获得的空间较小。
堆:堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。由此可见,堆获得的空间比较灵活,也比较大。

2.6存取效率的比较

chars1[]="aaaaaaaaaaaaaaa";
char*s2="bbbbbbbbbbbbbbbbb";
aaaaaaaaaaa是在运行时刻赋值的;
而bbbbbbbbbbb是在编译时就确定的;
但是,在以后的存取中,在栈上的数组比指针所指向的字符串(例如堆)快。
比如:
#include
voidmain()
{
chara=1;
charc[]="1234567890";
char*p="1234567890";
a=c[1];
a=p[1];
return;
}
对应的汇编代码
10:a=c[1];
004010678A4DF1movcl,byteptr[ebp-0Fh]
0040106A884DFCmovbyteptr[ebp-4],cl
11:a=p[1];
0040106D8B55ECmovedx,dwordptr[ebp-14h]
004010708A4201moval,byteptr[edx+1]
004010738845FCmovbyteptr[ebp-4],al
第一种在读取时直接就把字符串中的元素读到寄存器cl中,而第二种则要先把指针值读到edx中,在根据edx读取字符,显然慢了。


2.7小结:
堆和栈的区别可以用如下的比喻来看出:
使用栈就象我们去饭馆里吃饭,只管点菜(发出申请)、付钱、和吃(使用),吃饱了就走,不必理会切菜、洗菜等准备工作和洗碗、刷锅等扫尾工作,他的好处是快捷,但是自由度小。
使用堆就象是自己动手做喜欢吃的菜肴,比较麻烦,但是比较符合自己的口味,而且自由度大。

堆、栈

堆空间 的 内存分配属于用户级的内存分配,所分配的内存需要手动释放,否则会造成内存泄漏。当然,在应用程序销毁时,也能得到释放。在32位的系统中堆得大小可达 4G,可见堆得空间可以很大。但是堆的频繁分配与释放可能会带来内存碎片,也可能会造成内核模式和用户模式(Unix/Linux的内核态和用户态)频 繁切换和申请内存,带来性能上的损失。例如可能会为了分配一块内存,C/C++库函数会按照一定的算法 在 堆内存中搜索,看是否有可用的足够大小的空间。如果没有足够大小的空间(可能是由于内存碎片太多),就有可能通过执行系统调用去增加程序数据段的内存空 间,这样就有机会分到足够大小的内存,然后再返回。但是,我们要看到堆为我们提供了足够的对内存使用的灵活性。特别是在某些时候,动态地分配内存能为我们 大大的节约内存空间。

栈空间 的 内存分配则由系统负责管理的,是系统级的内存分配,一般不需要我们手动的控制。局部变量、以及被调用的子程序的返回地址以及寄存器信息都存放在栈中。我们 知道栈是FIFO(先进先出)的结构,因而栈空间上的内存始终是连续占用的,不会出现内存碎片。然而,栈的大小是有限制的。

例如,在VC6 下面,默认的栈空间大小是 1M 。当然,可以修改:

打开工程,依次操作菜单如下: Project->Setting->Link ,在 Category 中选中 Output ,然后在 Reserve 中设定堆栈的最大值和 commit

堆与栈

堆与栈是两个不同的概念,但是我们习惯上却经常说“堆栈”这个词,这造成了许多的误会。因此,我们还要了解堆与栈的联系与区别

首先,我们用一张图来直观的说明堆、栈在内存上的位置关系。

内存图示

3.13 栈大小和堆大小

在Symbian OS中,默认情况下,一个程序的默认栈大小是8KB。但是可以通过在项目的MMP文件中使用关键字EPOCSTACKSIZE来调整其大小。比如:

  1. EPOCSTACKSIZE0x5000

上面的语句将可执行文件的栈大小改为20KB(十六进制的0x5000字节,或十进制的20 480字节)。栈大小最大可以为80KB。

默认最小的堆大小是4KB,最大的堆大小是1MB。两者都可调整,同样也是在项目的MMP文件中用宏EPOCHEAPSIZE来调整。比如:

  1. EPOCHEAPSIZE0x50000x10000

上面的语句把默认最小的堆大小改为20KB(0x5000字节),并将最大的堆大小改为1MB(0x10000字节)。这意味着什么呢?

如果可用的内存小于20KB,那么将不能再启动进程。

进程不能耗用超过1MB的堆内存。

分享到:
评论

相关推荐

    堆和栈的区别,详细描述了堆栈的分配和使用原理

    在实际编程中,合理使用栈和堆可以提高程序性能。对于小规模、生命周期短的对象,使用栈更高效;对于大规模、生命周期不确定的对象,堆可能是更好的选择。此外,还可以使用智能指针等工具帮助管理堆内存,减少内存...

    堆栈平衡(简单main函数演示)

    堆栈平衡是计算机编程领域中一个至关重要的概念,特别是在低级语言如汇编语言中,理解和掌握堆栈平衡对于程序的正确执行至关重要。堆栈平衡指的是在程序执行过程中,堆栈上的数据在函数调用和返回时能够保持一致性,...

    两个堆栈共用存储空间

    3. **平衡策略**:在两个栈的使用过程中,可以通过某种策略来保持它们的空间使用平衡。例如,当一个栈即将满时,可以将元素转移到另一个栈中,从而确保空间的充分利用。这需要设计额外的算法来监控和调整栈的状态。 ...

    堆栈平衡ppt

    - 使用`move ax,0CCCCCCCCh`和`rep stos dwordptr [edi]`指令来初始化栈空间的值为`0xCCCCCCCC`。 5. **局部变量操作**: - 使用`move`和`add`指令对局部变量进行操作。例如,在`a = a + 3;`语句中,通过`move ax...

    数据结构课程作业 单链表 双链表 线性表 堆栈 等课程编程作业

    堆栈是一种后进先出(LIFO)的数据结构,操作主要集中在栈顶,包括压栈(将元素放入栈顶)和弹栈(移除栈顶元素)。堆栈常用于函数调用、表达式求值和深度优先搜索等场景。 二叉树是一种非线性的数据结构,每个节点...

    堆栈溢出了怎么办?.pdf

    - **优化内存分配**:减少不必要的内存分配,避免过度使用栈空间。 - **使用动态内存分配**:考虑将大量数据存储在堆上,而非栈上,以降低溢出风险。 - **代码审查**:团队成员间进行代码审查,发现可能的潜在...

    从汇编到c 调用约定 堆栈原理

    平衡栈空间 ``` 通过增加ESP的值来移除栈上的参数。 4. **恢复环境**:最后,通过一系列操作来恢复函数调用前的状态: ``` 00401071 pop edi ; 恢复EDI 00401072 pop esi ; 恢复ESI 00401073 pop ebx ; 恢复...

    Eclipse堆栈和内存大小设置借鉴.pdf

    Eclipse是一款广泛使用的Java开发集成环境,其性能和稳定性很大程度上取决于如何正确配置内存和堆栈大小。在处理大型项目或进行性能密集型操作时,调整Eclipse的内存设置至关重要,以防止因内存不足导致的崩溃或缓慢...

    栈溢出漏洞

    这种漏洞源于程序在使用栈空间时没有正确地管理内存,导致数据超出预分配的栈空间,进而影响到栈上的其他变量或者覆盖返回地址。在“湖湘杯2016网络安全技能大赛pwnme”中,参赛者可能需要通过利用栈溢出漏洞来解决...

    嵌入式软件中基于栈的错误追踪机制设计

    堆栈的大小可根据开发阶段和运行阶段的不同需求进行调整,以平衡调试需求和内存使用。 接下来,文章提到了统一的错误描述字典表。将错误代码映射到具体的错误描述,可以提供一致的用户反馈,同时降低内存占用。通过...

    JAVA中的内存分配策略

    综上所述,JAVA中的内存分配策略包括静态存储分配、栈式存储分配和堆式存储分配。每种策略都有其适用场景和限制条件。JVM采用了基于堆栈的设计来管理和优化内存使用,同时通过垃圾回收机制自动管理对象的生命周期,...

    嵌入式多媒体数据结构堆栈调度控制算法.pdf

    堆栈能够保存数据项,通过“压栈”(push)和“弹栈”(pop)操作进行数据的存储和检索。在嵌入式多媒体系统中,堆栈可以有效地管理数据流、控制任务调度,以及保证数据处理的及时性。 然而,传统的控制算法基于...

    uCOS51重入问题的解决.doc

    选择最大形参和局部变量需求的任务函数的堆栈大小作为仿真堆栈大小,从而确定唯一用户堆栈空间大小。这个大小可以通过宏定义在OS_CFG.H文件中,命名为MaxStkSize。 由于51的SP寄存器只有8位,不能直接在64K空间中...

    c++基础概念.doc

    "C++ 基础概念" C++ 是一种高效、灵活、可移植的编程语言,广泛应用于操作系统、游戏、...堆(Heap)和栈(Stack)是两种不同的内存区域。堆用于存储动态申请的内存空间。栈用于存储函数调用时的局部变量和函数参数。

    JVM大厂面试题目集锦、垃圾回收、内存优化、内存结构全方位题目(附答案)

    首先,JVM内存主要分为五个区域:堆区、栈区、方法区、本地方法栈和程序计数器。堆区是所有对象的诞生地,包括数组,分为新生代(Eden + Survivor,Survivor又分为From和To空间)和老年代。栈区主要用于存储方法调用...

    算法设计与分析第七章1

    若能合理地管理栈空间,确实有可能实现每次操作的平摊成本为O(1)。 8. 二进制计数器的decrement()操作,通过上述分析方法,同样可以计算其平摊运行时间。在特定实现下,也可以达到O(1)的平摊成本。 9. 动态表的...

    <数据结构>课件压缩包ppt

    排序是对数据进行排列的过程,常见的排序算法有冒泡排序、选择排序、插入排序、快速排序、归并排序和堆排序等。快速排序和归并排序是高效的分治算法,而堆排序则利用了堆这种数据结构。 本压缩包提供的课件将帮助你...

    08-为何二叉树重要.md

    堆内存用于存储对象等引用类型数据,而栈内存则用于存储基本数据类型和函数执行上下文。 总的来说,二叉树及其扩展结构在前端面试中考察的频率非常高,因为它们不仅仅是数据结构的基础,更是掌握算法思维的必要环节...

    字符串内存分析.zip

    2. 堆栈溢出:如果字符串过长或者过多的局部变量导致栈空间耗尽,会发生栈溢出。这可能破坏相邻数据,甚至导致程序崩溃。 3. 字符串拷贝与效率:字符串操作如复制、连接(concatenation)可能涉及内存拷贝,过多的...

Global site tag (gtag.js) - Google Analytics