不合类型的变量在内存中的分派与开释(详解)
添加时间:2013-7-29 点击量:
一、堆和栈根蒂根基概念:
<1>堆和栈(理论项目组)
&#160;&#160;&#160;&#160; 堆的概念:
- 这块内存是有很多内存块构成,很像鞭炮一样串在一根绳索上,但这些内存块的大小不一样,存储在链表布局中的结点中。操纵体系有一个记录余暇内存地址的链表,当体系收到法度的申请时,会遍历该链表,寻找第一个空间大于所申请的堆节点,然后将该节点从余暇节点链表中删除,并将该节点的空间分派给法度。
&#160;&#160;&#160;&#160;&#160; 栈的概念:
- 这块内存是连气儿的,就比如是一个数组,所以你在内存分派的时辰,会发明变量地址是连气儿的在函数调用时第一个进栈的主函数中的下一条指令(函数调用语句的下一条可履行语句)的地址然后是函数 的各个参数,在大多半的C编译器中,参数是由右往左入栈,然后是函数中的局部变量。
<2>堆和栈(实际代码项目组)
&#160;
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
int a=10;
char pt;
int main(int argc, char argv[])
{
printf("全局存储区中数据地址(无初值):0 x%08x\n",pt);
printf("全局存储区中数据地址(有初值):0 x%08x =%d\n",&a,a);
const int MAXIN = 100;
int p = (int)malloc(MAXIN sizeof(int));//堆中数据地址
printf("堆中数据地址:0 x%08x\n",p);
static int s_m=5;
printf("静态数据地址(有初值):0 x%08x =%d\n",&s_m,s_m);
static int s_j;
printf("静态数据地址(无初值):0 x%08x =%d\n",&s_j,s_j);
return 0;
}
&#160;
从以上代码可知:
1.栈,就是那些由编译器在须要的时辰分派,在不须要的时辰主动清楚的变量的存储区。里面的变量凡是是局部变量、函数参数等。
2.堆,就是那些由new分派的内存块,他们的开释编译器不去管,由我们的应用法度去把握,一般一个new就要对应一个。若是法度员没有开释掉,那么在法度停止后,操纵体系会主动收受接管。
3.存储区,就是那些由malloc等分派的内存块,他和堆是十分类似的,不过它是用free来停止本身的生命的。
4.全局/静态存储区,全局变量和静态变量被分派到同一块内存中,在以前的C说话中,全局变量又分为初始化的和未初始化的,在C++里面没有这个区分了,他们共同占用同一块内存区。
5.常量存储区,这是一块斗劲特别的存储区,他们里面存放的是常量,不容许批改(当然,你要经由过程非合法手段也可以批改)
二、堆和栈差别对比
-
经管体式格式不合:对于栈来讲,是由编译器主动经管,无需我们手工把握;
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; 对于堆来讲,释放工作由法度员完成,轻易产生memory leak(内存泄漏)
-
空间大小不合:一般来说,在32位体系下, 堆内存可以达到4G的空间,从这个角度解析堆内存几乎是没有什么限制的,
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; 对于栈来讲,一般都是有必然的空间大小的,一般栈的空间大小是1M
-
可否产生碎片不合:对于堆来讲,频繁的new/势必会造成内存空间不连气儿,从而造成多量的碎片,使法度效力降落
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; 对于栈来讲,则不会存在这个题目,因为栈是进步前辈后出的队列,他们是一一对应的。
-
发展标的目标不合:对于堆来讲,发展标的目标是向上的,也就是向着内存地址增长的标的目标;
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; 对于栈来讲,发展标的目标是向下的,也就是向着内存地址减小的标的目标增长
-
分派体式格式不合:堆是动态分派的,没有静态分派的堆。
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; 栈有2种分派体式格式:静态分派和动态分派。1>静态分派是编译器完成的,比如局部变量;2>动态分派由
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; alloca函数进行分派
-
分派效力不合:栈是机械体系供给的数据布局,策画机会在底层对栈供给支撑;分队专门的存放器存放栈的地址,压栈出
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; 栈都有专门的指令履行,这就决意了站的效力斗劲高。
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; 堆则是C/C++函数库供给的,它的机制是很错杂的;例如为了分派一块内存,库函数会遵守必然的算法在
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; 堆内存中搜刮可用的足够大小的空间,若是没有足够大小的空间,就有可能调用体系功能区增长
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; 法度数据段的内存空间,如许就有机会分到足够大小的内存,然掉队行返回。
-
总结:从这里我们可以看到,堆和栈比拟,因为多量new/的应用,轻易造成多量的内存碎片;因为没有专门的体系支撑,效力很低;因为可能激发用户态 和核心态的切换,内存的申请,价格变得加倍昂贵。所以栈在法度中是应用广泛泛的,就算是函数的调用也哄骗栈去完成,函数调用过程中的参数,返回地址, EBP和局部变量都采取栈的体式格式存放。所以,我们推荐大师尽量用栈,而不是用堆。
读书,不要想着实用,更不要有功利心。读书只为了自身的修养。邂逅一本好书如同邂逅一位知己,邂逅一个完美之人。有时心生敬意,有时怦然心动。仿佛你心底埋藏多年的话,作者替你说了出来,你们在时光深处倾心相遇的一瞬间,情投意合,心旷神怡。
一、堆和栈根蒂根基概念:
<1>堆和栈(理论项目组)
&#160;&#160;&#160;&#160; 堆的概念:
&#160;&#160;&#160;&#160;&#160; 栈的概念:
<2>堆和栈(实际代码项目组)
&#160;
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
int a=10;
char pt;
int main(int argc, char argv[])
{
printf("全局存储区中数据地址(无初值):0 x%08x\n",pt);
printf("全局存储区中数据地址(有初值):0 x%08x =%d\n",&a,a);
const int MAXIN = 100;
int p = (int)malloc(MAXIN sizeof(int));//堆中数据地址
printf("堆中数据地址:0 x%08x\n",p);
static int s_m=5;
printf("静态数据地址(有初值):0 x%08x =%d\n",&s_m,s_m);
static int s_j;
printf("静态数据地址(无初值):0 x%08x =%d\n",&s_j,s_j);
return 0;
}
&#160;
从以上代码可知:
1.栈,就是那些由编译器在须要的时辰分派,在不须要的时辰主动清楚的变量的存储区。里面的变量凡是是局部变量、函数参数等。
2.堆,就是那些由new分派的内存块,他们的开释编译器不去管,由我们的应用法度去把握,一般一个new就要对应一个。若是法度员没有开释掉,那么在法度停止后,操纵体系会主动收受接管。
3.存储区,就是那些由malloc等分派的内存块,他和堆是十分类似的,不过它是用free来停止本身的生命的。
4.全局/静态存储区,全局变量和静态变量被分派到同一块内存中,在以前的C说话中,全局变量又分为初始化的和未初始化的,在C++里面没有这个区分了,他们共同占用同一块内存区。
5.常量存储区,这是一块斗劲特别的存储区,他们里面存放的是常量,不容许批改(当然,你要经由过程非合法手段也可以批改)
二、堆和栈差别对比
经管体式格式不合:对于栈来讲,是由编译器主动经管,无需我们手工把握;
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; 对于堆来讲,释放工作由法度员完成,轻易产生memory leak(内存泄漏)
空间大小不合:一般来说,在32位体系下, 堆内存可以达到4G的空间,从这个角度解析堆内存几乎是没有什么限制的,
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; 对于栈来讲,一般都是有必然的空间大小的,一般栈的空间大小是1M
可否产生碎片不合:对于堆来讲,频繁的new/势必会造成内存空间不连气儿,从而造成多量的碎片,使法度效力降落
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; 对于栈来讲,则不会存在这个题目,因为栈是进步前辈后出的队列,他们是一一对应的。
发展标的目标不合:对于堆来讲,发展标的目标是向上的,也就是向着内存地址增长的标的目标;
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; 对于栈来讲,发展标的目标是向下的,也就是向着内存地址减小的标的目标增长
分派体式格式不合:堆是动态分派的,没有静态分派的堆。
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; 栈有2种分派体式格式:静态分派和动态分派。1>静态分派是编译器完成的,比如局部变量;2>动态分派由
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; alloca函数进行分派
分派效力不合:栈是机械体系供给的数据布局,策画机会在底层对栈供给支撑;分队专门的存放器存放栈的地址,压栈出
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; 栈都有专门的指令履行,这就决意了站的效力斗劲高。
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; 堆则是C/C++函数库供给的,它的机制是很错杂的;例如为了分派一块内存,库函数会遵守必然的算法在
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; 堆内存中搜刮可用的足够大小的空间,若是没有足够大小的空间,就有可能调用体系功能区增长
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; 法度数据段的内存空间,如许就有机会分到足够大小的内存,然掉队行返回。
总结:从这里我们可以看到,堆和栈比拟,因为多量new/的应用,轻易造成多量的内存碎片;因为没有专门的体系支撑,效力很低;因为可能激发用户态 和核心态的切换,内存的申请,价格变得加倍昂贵。所以栈在法度中是应用广泛泛的,就算是函数的调用也哄骗栈去完成,函数调用过程中的参数,返回地址, EBP和局部变量都采取栈的体式格式存放。所以,我们推荐大师尽量用栈,而不是用堆。