标签:
1. 堆分配和栈分配的差别
一般认为在
c
中分为这几个存储区
栈堆全局区:
1
栈
有编译器自动分配释放
2
堆
一般由程序员分配释放,若程序员不释放,程序结束时可能由
OS
回收
3
全局区(静态区),全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和
未初始化的静态变量在相邻的另一块区域。
程序结束释放
4
另外还有一个专门放常量的地方。
程序结束释放
区别:
在函数体中定义的变量通常是在栈上,用
malloc,
calloc,
realloc
等分配内存的函数分配得到的就是在堆上。在所有函数体外定义
的是全局量,加了
static
修饰符后不管在哪里都存放在全局区(静态区)
,
在所有函数体外定义的
static
变量表示在该文件中有效,不能
extern
到别的文件用,在函数体内定义的
static
表示只在该函数体内有效。另外,函数中的
"adgfdf "
这样的字符串存放在常量区。比
如:
代码:
int a = 0;
//
全局初始化区
char
*p1;
//
全局未初始化区
main()
int
b;
//
栈
char
s[]
=
"abc ";
//
栈
char
*p2;
//
栈
char
*p3
=
"123456 ";
//123456\0
在常量区,
p3
在栈上。
static
int
c
//
全局(静态)初始化区
p1
=
(char
*)malloc(10);
p2
=
(char
*)malloc(20);
//
分配得来得
10
和
20
字节的区域就在堆区。
strcpy(p1,
"123456 ");
//123456\0
放在常量区,编译器可能会将它与
p3
所指向的
"123456 "
优化成一块。
还有就是函数调用时会在栈上有一系列的保留现场及传递参数的操作。栈的空间大小有限定,
vc
的缺省是
2M
。栈
不够用的情况一般是程序中分配了大量数组和递归函数层次太深。有一点必须知道,当一个函数调用完返回后它会释放该函数中所
有的栈空间。栈是由编译器自动管理的,不用你操心。
堆是动态分配内存的,并且你可以分配使用很大的内存。但是用不好会产生内存泄漏。并且频繁地
malloc
和
free
会
产生内存碎片(有点类似磁盘碎片),因为
c
分配动态内存时是寻找匹配的内存的。而用栈则不会产生碎片。
在栈上存取数据比通过指针在堆上存取数据快些。一般大家说的堆栈和栈是一样的,就是栈
(stack)
,而说堆时才
是堆
heap
。栈是先入后出的,一般是由高地址向低地址生长。
堆
(heap)
和栈
(stack)
:
堆
(heap)
和栈
(stack)
是
C/C++
编程不可避免会碰到的两个基本概念。首先,这两个概念都可以在讲数据结构的书中找到,他们都是基本的数据结构,虽然栈更为简单一些。在具体的
C/C++
编程框架中,这两个概念并不是并行的。对底层机器代码的研究可以揭示,
栈是机器系统提供的数据结构,而堆则是C/C++函数库提供的。
具体地说,
现代计算机
(
串行执行机制
)
,都直接在代码底层支持栈的数据结构。
这体现在,
有专门的寄存器指向栈
所在的地址,有专门的机器指令完成数据入栈出栈的操作。这种机制的特点是效率高,支持的数据有限,一般是整数,指针,浮点
数等系统直接支持的数据类型,并不直接支持其他的数据结构。因为栈的这种特点,对栈的使用在程序中是非常频繁的。对子程序
的调用就是直接利用栈完成的。机器的
call
指令里隐含了把返回地址推入栈,然后跳转至子程序地址的操作,而子程序中的
ret
指令则
隐含从堆栈中弹出返回地址并跳转之的操作。
C/C++
中的自动变量是直接利用栈的例子,这也就是为什么当函数返回时,该函数的
自动变量自动失效的原因。
和栈不同,
堆的数据结构并不是由系统
(
无论是机器系统还是操作系统
)
支持的,
而是由函数库提供的。
基本的
malloc/realloc/free
函数维护了一套内部的堆数据结构。当程序使用这些函数去获得新的内存空间时,这套函数首先试图从内部堆中寻找可用的内存空
间,如果没有可以使用的内存空间,则试图利用系统调用来动态增加程序数据段的内存大小,新分配得到的空间首先被组织进内部
堆中去,然后再以适当的形式返回给调用者。当程序释放分配的内存空间时,这片内存空间被返回内部堆结构中,可能会被适当的
处理
(
比如和其他空闲空间合并成更大的空闲空间
)
,
以更适合下一次内存分配申请。
这套复杂的分配机制实际上相当于一个内存分配
的缓冲池
(Cache)
,使用这套机制有如下若干原因:
1.
系统调用可能不支持任意大小的内存分配。
有些系统的系统调用只支持固定大小及其倍数的内存请求。这样的话对于大量的小内存分类来说会造成浪费。
2. 系统调用申请内存可能是代价昂贵的。系统调用可能涉及用户态和核心态的转换。
3. 没有管理的内存分配在大量复杂内存的分配释放操作下很容易造成内存碎片。
标签:
原文地址:http://www.cnblogs.com/yeyublog/p/5734374.html