堆跟栈的区别

程序的内存分配
一个由C/C++编译的程序占用的内存分为以下几个部分:

1、栈区(stack), 由编译器自动分配释放,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。

2、堆区(heap) , 一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事。

3、全局区(静态区)(static),全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。 - 程序结束后由系统释放 

4、文字常量区 ,常量字符串就是放在这里的。 程序结束后由系统释放 

5、程序代码区,存放函数体的二进制代码。 

堆跟栈的主要区别
1.管理方式不同
栈,由编译器自动管理,无需程序员手工控制;堆:产生和释放由程序员控制。

2. 空间大小不同
栈的空间有限;堆内存可以达到4G(跟电脑配置 有关系)。

3. 能否产生碎片不同
栈不会产生碎片,因为栈是种先进后出的队列。堆则容易产生碎片,多次的new/delete 会造成内存的不连续,从而造成大量的碎片。

4. 生长方向不同
堆的生长方式是向上的,栈是向下的。

5. 分配方式不同
堆是动态分配的。栈可以是静态分配和动态分配两种,但是栈的动态分配由编译器释放。

6. 缓存级别不同:
  1)、栈使用的是一级缓存, 他们通常都是被调用时处于存储空间中,调用完毕立即释放;
  2)、堆是存放在二级缓存中,生命周期由虚拟机的垃圾回收算法来决定(并不是一旦成为孤儿对象就能被回收)。所以调用这些对象的速度要相对来得低一些。

7. 分配效率不同
  栈是机器系统提供的数据结构,计算机底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令。堆则是由C/C++函数库提供,库函数会按照一定的算法在堆内存中搜索可用的足够大小的空间,如果没有足够大小的空间(可能是由于内存碎片太多),就有可能调用系统功能去增加程序数据段的内存空间,这样就有机会分到足够大小的内存,然后进行返回。显然,堆的效率比栈要低得多。
  堆和栈相比,由于大量new/delete的使用,容易造成大量的内存碎片;由于没有专门的系统支持,效率很低;由于可能引发用户态和核心态的切换,内存的申请,代价变得更加昂贵。所以栈在程序中是应用最广泛的,就算是函数的调用也利用栈去完成,函数调用过程中的参数,返回地址,EBP和局部变量都采用栈的方式存放。所以,我们推荐大家 尽量用栈,而不是用堆。
  栈和堆相比不是那么灵活,有时候分配大量的内存空间,还是用堆好一些。
  无论是堆还是栈,都要防止越界现象的发生。

栈到底有多少大
下面的代码,在vs2008运行时,是会报错的:

#include "stdafx.h"
#include <stdlib.h>
 
int _tmain(int argc, _TCHAR* argv[])
{
    int a[1024][1024];
 
    system("pause");
    return 0;
}
消耗栈空间主要有两种操作:函数调用和局部变量。在写递归程序时,大家就容易碰到栈空间溢出的情况。上述代码就是局部变量申请引发栈溢出错误的例子。在vs2008中测试,具体的错误名称为:stack overflow,即栈发生溢出,也就是说申请的空间a[1024][1024]超出了栈的大小,所以出现栈溢出的错误。

栈到底有多少大呢?通过下述的代码,在vs2008下的输出为1011kB。

#include <stdlib.h>
#include <iostream>
#include <windows.h>
using namespace std;
 
int stack_opt(int & count)
{
    int a = 1;
 
    while(1)
    {
        _asm{ push a} //消耗栈空间
        count++;
    }
}
 
int _tmain(int argc, _TCHAR* argv[])
{
    int count = 0; 
 
    __try{
        stack_opt(count);
    }
    __except(GetExceptionCode()==STATUS_STACK_OVERFLOW ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH){
        cout << "exception" << endl;
        cout << "the count is " << (count*4/1024) << "kB" << endl;
    }
 
    system("pause");
    return 0;
}

注意:调用stack_opt 也会涉及对栈的操作,消耗栈的空间,但是此处基本上没有影响。一次函数调用消耗的栈空间十分有限(几个字节而已),这并不妨碍大家对栈大小的理解。

在堆上最大可申请空间有多大
如果申请的空间过大,栈不够,那该怎么处理呢?这就要说到堆,我们平常使用的malloc语句就是在堆上进行空间申请,一般申请几百兆空间也不是问题。那么在堆上可以最大可申请多少的空间?

#include <stdlib.h>
#include <stdio.h>
 
#define UNIT_SIZE (100*1024*1024)//100M
 
int main(int argc, char* argv[])
{
    unsigned long max = 0;
    char* p = NULL;
 
    while(1){
        max++;
        p = (char*)malloc(max*UNIT_SIZE);
 
        if(p != NULL){
            printf("%d ", max);//申请成功则输出
            free(p);
        }else{
            printf("frame size: %ld\n", max-1);//输出申请的最大空间
            break;
        }
    }
    getchar();
    return 0;
}

上述代码,在我的机器上(Win7、8G内存、vs2008),最大能申请14*100M的大小,也就是1.4G左右。
————————————————

                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
                        
原文链接:https://blog.youkuaiyun.com/hellokandy/article/details/52937652

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值