c++中内存分配方式

来源:互联网 发布:华为 穆斯林 知乎 编辑:程序博客网 时间:2024/06/14 10:44
一个由C/C++编译程序占用内存分为以下几个部分:
1、栈区(stack):由编译器自动分配释放 ,存放函数参数值,局部变量值等。其操作方式类似于数据结构中栈。
2、堆区(heap):一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收,它与数据结构中堆是两回事,分配方式倒是类似于链表。
3、全局区(静态区)(static):全局变量和静态变量存储是放在一块,初始化全局变量和静态变量在一块区域,未初始化全局变量和未初始化静态变量在相邻另一块区域。程序结束后由系统释放。
4、文字常量区 —常量字符串就是放在这里。 程序结束后由系统释放
5、程序代码区—存放函数体二进制代码。

二、例子程序

//main.cppint a = 0; 全局初始化区char *p1; 全局未初始化区main(){    int b; //栈    char s[] = "abc"; //s.栈    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"优化成一个地方。}
二、堆和栈的区别
2.1申请方式
stack:由系统自动分配。 例如,声明在函数中一个局部变量 int b; 系统自动在栈中为b开辟空间
heap:需要程序员自己申请,并指明大小,在c中malloc函数
如p1 = (char *)malloc(10);
在C++中用new运算符
如p2 = (char *)malloc(10);

但是注意p1、p2本身是在栈中。

2.2申请后系统响应
栈:只要栈剩余空间大于所申请空间,系统将为程序提供内存,否则将报异常提示栈溢出。

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

2.3申请大小限制

栈:在Windows下,栈是向低地址扩展数据结构,是一块连续内存区域。这句话意思是栈顶地址和栈最大容量是系统预先规定好,如果申请空间超过栈剩余空间时,将提示"stack overflow"。因此,能从栈获得空间较小。

堆:堆是向高地址扩展数据结构,是不连续内存区域。这是由于系统是用链表来存储空闲内存地址,自然是不连续,而链表遍历方向是由低地址向高地址。堆大小受限于计算机系统中有效虚拟内存。由此可见,堆获得空间比较灵活,也比较大。

2.4申请效率比较
栈由系统自动分配,速度较快。但程序员是无法控制。
堆是由new分配内存,一般速度比较慢,而且容易产生内存碎片,不过用起来最方便.

另外,在WINDOWS下,最好方式是用VirtualAlloc分配内存,他不是在堆,也不是在栈是直接在进程地址空间中保留一快内存,虽然用起来最不方便。但是速度快,也最灵活。

2.5堆和栈中存储内容
栈: 在函数调用时,第一个进栈是主函数中后下一条指令(函数调用语句下一条可执行语句)地址,然后是函数各个参数,在大多数C编译器中,参数是由右往左入栈,然后是函数中局部变量。注意静态变量是不入栈。当本次函数调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向最开始存地址,也就是主函数中下一条指令,程序由该点继续运行。

堆:一般是在堆头部用一个字节存放堆大小,堆中具体内容由程序员安排。

2.6存取效率比较
char s1[] = "aaaaaaaaaaaaaaa";
char *s2 = "bbbbbbbbbbbbbbbbb";
aaaaaaaaaaa是在运行时刻赋值
而bbbbbbbbbbb是在编译时就确定
但是,在以后存取中,在栈上数组比指针所指向字符串(例如堆)快。
比如:

void main(){    char a = 1;    char c[] = "1234567890";    char *p ="1234567890";    a = c[1];    a = p[1];    return;}
对应汇编代码
10: a = c[1];
00401067 8A 4D F1 mov cl,byte ptr [ebp-0Fh]
0040106A 88 4D FC mov byte ptr [ebp-4],cl
11: a = p[1];
0040106D 8B 55 EC mov edx,dword ptr [ebp-14h]
00401070 8A 42 01 mov al,byte ptr [edx+1]
00401073 88 45 FC mov byte ptr [ebp-4],al

第一种在读取时直接就把字符串中元素读到寄存器cl中,而第二种则要先把指针值读到edx中,在根据edx读取字符,显然慢了。

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

为什么说在堆上分配内存比在栈上分配内存慢?

堆空间开辟需要用系统函数,栈上直接修改指针,堆空间管理需要系统记帐,栈上空间可以由编译器管理或是保存在某个处理器寄存器中。堆空间释放需要系统管理,栈上释放可以直接丢弃。堆空间需要通过栈上指针间接引用,所以访问会慢。

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 手机上办进京证怎么办 杭州公共自行车还车点满了怎么办 法院判决书下来对方不给钱怎么办 抓进看守所的人怎么办 在拘留所里病重抢救怎么办 昆明公租房户型确认后怎么办 18年工作好难找怎么办 我没工作了怎么办2018 婚姻质量差不幸福该怎么办 吸毒犯戒毒所不收怎么办 信用卡到期人进拘留所怎么办? 人在拘留所信用卡逾期怎么办 探视权不让接走怎么办 医保过了缴费期怎么办 充电宝充手机慢怎么办 执行局执行不到钱怎么办 小孩挖耳朵疼了怎么办 挖耳朵挖破了怎么办 挖耳朵皮挖破了耳鸣怎么办 北京自考证丢啦怎么办 不服检察院的答复函该怎么办 检察院控申答复函不复怎么办 在看守所里疯了怎么办 第一次吸毒拘留五天第二次会怎么办 被派出所拘留15天怎么办 老公从拘留所出来聪明老婆怎么办 中信信用卡忘记还款了怎么办 监狱的犯人病了怎么办 判缓期间在行政拘留怎么办 法院拘留15天工作怎么办 高血压签定了无期限合同怎么办 法院司法拘留找不到人怎么办 c1骑摩托车要拘留怎么办 欠钱的找不到人怎么办 治安拘留人跑了怎么办 行政拘留拘留所不收应该怎么办 在看守所被打了怎么办 取保候审超过12个月怎么办 拘留20天还没有判刑怎么办 被打了没有证据怎么办 拘留37天后没有放人怎么办