动态存储分配和静态存储分配的区别,静态内存分配和动态内存分配
在C中,我们使用molloc,free动态分配来释放内存,而在C中,我们可以使用新的delete运算符。例如,我们可以用两种方式在C中定义数组:
1.静态分配内存:比如int a[10];
2.使用新的动态定义:例如:int * p=new int[10];
那么这两种方法有什么区别呢?
实际上,使用新建、删除等。叫做“动态分配内存”。我们一般定义int a[10]数组是在函数的整个生命周期内,也就是说,如果a[10]数组是在一个函数中定义的,那么a[10]数组从定义的时候就一直存在,直到这个函数执行完毕。它是静态的,不能由程序员自动分配和释放。所谓“内存的动态分配”是动态的,因为我们可以在函数中定义分配,随时释放,这是动态分配和一般的空间分配的一个很大的区别。另外,我们一般定义一个[10],如果它是在函数内部定义的,但它是被静态没有修改的存储内存的堆栈空间,这个空间里的数据由编译器自动分配释放;但是,动态分配的数据空间存储在堆中。一般是程序员分配释放,系统不会自动释放。因此,如果使用new来动态分配内存中的堆空间,则必须使用delete来释放它,即使该函数已经执行。
c/c程序占用的内存分为以下几部分
1、堆栈区(stack);
编译器自动分配和释放、存储函数的参数值、局部变量的值等。堆栈是先进后出的。我们可以看到,堆栈被视为一个寄存器,一个用于交换临时数据的内存区域。
2.许多
通常,程序员使用malloc和其他函数来分配释放。如果程序员不释放它,程序运行时操作系统可能回收也可能不回收。
3.全局区域(静态区域)
全局变量和局部静态变量都存储在这里。已初始化的全局变量和静态变量在一个区域,未初始化的全局变量和已初始化的静态变量在一个相邻的区域(一般称为(BSS区域)),程序结束后会被系统释放。堆的大小不是固定的,而是可以动态扩展或收缩的。
4.文本常量区域
常量存储在这里。程序通过验收后由系统发布;
5.程序代码区
存储函数体的二进制代码;
以及堆和栈的理论知识。
1应用方法
堆栈:
由系统自动分配。比如在函数中声明一个局部变量int b;系统自动在堆栈中为B打开空间
堆:
需要程序员自己申请,并在c中注明malloc函数的大小。
P1=(char *)马洛克(10);
在c中使用new运算符。
但是请注意,p1本身在堆栈中。
2应用后系统的响应
堆栈:只要堆栈剩余空间大于请求空间,系统就会为程序提供内存,否则会报告异常提示堆栈溢出。
Heap:首先你要知道操作系统有一个链表来记录空闲内存地址。当系统收到程序的申请时,会遍历链表,找到第一个空间大于申请空间的堆节点,然后从空闲节点链表中删除该节点,将该节点的空间分配给程序。另外,对于大多数系统来说,这种分配的大小会记录在这个内存空间的第一个地址,这样代码中的delete语句就可以正确地释放这个内存空间。此外,因为找到的堆节点的大小不一定完全等于应用程序的大小,所以系统会自动将多余的部分放回自由链表中。
3应用程序大小的限制
堆栈:在Windows下,堆栈是一种扩展到低位地址的数据结构,是连续内存的一个区域。这句话的意思是栈顶的地址和栈的最大容量是由系统预先确定的。在WINDOWS下,堆栈的大小是2M(有人说1M,简而言之,是编译时确定的常数)。如果应用的空间超过堆栈的剩余空间,将会提示溢出。因此,堆栈中的可用空间很小。
Heap: Heap是扩展到高位地址的数据结构,是一个不连续的内存区域。这是因为系统使用链表存储空闲内存地址,自然是不连续的,链表的遍历方向是从低位地址到高位地址。堆的大小受到计算机系统中可用虚拟内存的限制。可见堆获得的空间更灵活,更大。
4应用效率比较:
堆栈由系统自动分配,速度更快。但是程序员控制不了。
Heap是new分配的内存,一般比较慢,容易出现内存碎片,但是用起来最方便。
另外,在WINDOWS下,最好的方法是使用VirtualAlloc来分配内存。它不在堆里,也不在栈里,而是直接在进程的地址空间里保留一个内存的缓存,虽然用起来最不方便。但它是快速且最灵活的。
5堆和堆栈中的存储内容
堆栈:调用函数时,主函数中下一个指令(函数调用语句的下一个可执行语句)的地址是堆栈上的第一个,后面是函数的参数。在大多数C编译器中,参数从右到左堆叠,然后是函数中的局部变量。请注意,静态变量是不堆叠的。
当这个函数调用完成后,先将局部变量弹出堆栈,然后是参数,最后堆栈顶部的指针指向第一个存储的地址,也就是主函数中的下一条指令,程序从这里继续运行。
堆:通常,在堆的头部使用一个字节来存储堆的大小。堆的具体内容由程序员安排。
6访问效率的比较
char S1[]= aaaaaaaaaaaaaaaa ;
char * s2= bbbbbbbbbbbbbbbbb//这个语句是这个字符串在堆里吗??
aaaaaaaaaa是在运行时分配的;
Bbbbbbbbbbb是在编译时确定的;
但是在以后的访问中,栈上的数组比指针指向的字符串(比如heap)要快。
例如:
#包含stdio.h
void main()
{
char a=1;
char c[]= 1234567890 ;
char * p= 1234567890
a=c[1];
a=p[1];
返回;
}
相应的装配代码
10:a=c[1];
00401067 8A 4D F1 mov cl,字节指针[ebp-0Fh]
0040106A 88 4D FC mov字节ptr [ebp-4],cl
11:a=p[1];
0040106D 8B 55 EC mov edx,dword ptr [ebp-14h]
00401070 8A 42 01 mov al,字节ptr [edx 1]
00401073 88 45 FC mov字节ptr [ebp-4],al
第一种是直接将字符串中的元素读入寄存器cl,第二种是先将指针值读入edx,根据edx读取字符时明显较慢。
注:本文是库特吧前期整理的资料,没有留下引用链接。如有侵权请告知库特吧。
本文来自特库巴http://www.tekuba.net/,原地址:http://www.tekuba.net/program/168/
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。