1申请方式
栈的申请:由系统自动分配空间。声明在函数中一个局部变量 int b; 系统自动在栈中为 b 开辟空间
堆的申请:需要自己申请,并且指明申请的大小。在 c 中 malloc 函数 如 p1 = (char *)malloc(10); 在c++中int *a=new int[100];
2申请空间后系统如何处理
对于栈:如果申请的空间小于栈的剩余空间,系统将为程序提供所需的空间。如果大于就报异常,提示栈溢出。
对于堆:在操作系统中有一个记录空闲地址的链表,当系统收到程序的请求时,会遍历该链表,从中找出第一个空间大于所申请的堆空间,然后将该空闲节点从链表中删除,将空间分配给程序。另外,对于大多数系统,会在这块内存空间中的首地址处记录本次分配的大小,这样,代码中的 delete 语句才能正确的释放本内存空间。另外由于找到的堆节点不一定正好等于申请的大小,系统会自动将多余的那部分重新放入链表中。
3申请大小的限制
栈:在Windows下栈是向低地址扩展的数据结构,是由高地址向低地址扩展的连续的空间。栈顶的地址和栈的容量是操作系统事先定义好的。在Windows下这个容量为2M(也有1M的,总之是事先规定好的容量)。如果申请的栈超过了剩余的空间会提示overflow.
堆:申请空间时,是从低地址向高地址扩展的。并且由于空闲的堆内存是由链表来存储的,所以他是不连续的。并且遍历链表时是从低地址向高地址扩展的。堆的大小受限于计算机有效的虚拟内存。
4申请的效率比较
栈由系统分配,效率较高,但是程序员无法控制。
堆是由程序员通过new或者malloc分配的,使用方便,但是容易产生内存碎片。
在 WINDOWS 下,最好的方式是用 VirtualAlloc 分配内存,他不是在堆,也不是在栈是直接在进程的地址空间中保留一快内存,虽然用起来最不方便。但是速度快,也最灵活。
5栈和堆中存储的内容
栈:在函数调用语句时,最先进栈的是函数调用语句的 下一条可执行语句的 地址。接着进栈的是函数的各个参数,在大多数的C编译器中参数是又右向左进栈的,然后函数中的局部变量入栈。注意:静态变量不入栈。
当出栈时,局部变量先出栈,然后是函数参数,最后调用函数的 下一条指令的地址 出栈(程序由该点继续运行)。
堆:一般堆的头部用一个直接存放堆的大小,其余的内容由程序员安排。
6存取效率的比较
char s1[] = "aaaaaaaaaaaaaaa";
char *s2 = "bbbbbbbbbbbbbbbbb";
aaaaaaaaaaa 是在运行时刻赋值的;
而 bbbbbbbbbbb 是在编译时就确定的;
但是,在以后的存取中,在栈上的数组比指针所指向的字符串 ( 例如堆 ) 快。
比如:
#include
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 读取字符,显然慢了。

被折叠的 条评论
为什么被折叠?



