程序的内存分配
一个由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