突然想起一直以来未能解释的一个c问题:
int n;
scanf("%d",&n);
char a[n];
即申请变成的数组,这个在编译阶段会出错。但用malloc、new之类分配内存则不会遇到这个问题。
一说是因为编译器会检测需要的堆栈空间的大小,如winodws默认的堆栈大小为1M,如需要的堆栈空间超出则会报错。变长数组使得这一检测没有结果,故而出错。而堆空间的使用在编译阶段则不做检查,故而没有问题。
Anyway,还不是很确定啦。
于是顺带复习了一下堆、栈等的关系,转载两篇文章吧。不过对于第二篇将内存分为五种的说法却是第一见,但其对堆、栈的区分讲的还是不错的,姑且一看吧。两篇文章较长,分开转载吧。
PS:总有人说局部变量的内存是在编译阶段分配的……实在很汗……编译链接不过生成exe文件。这个时候程序只存在于硬盘里,何来的内存分配?!很容易给初学者误解的。如下的解释应该比较清晰些:
栈空间是静态分配的,编译期就决定了相对地址。由编译器管理的。给局部变量分配的栈内存,通过数据栈指针和相对偏移访问, 数据栈指针存放在EBP中,相对偏移值在编译期决定。编译时,对于局部变量(比如char buf[10]),只不过生成了这样一条语句:
sub esp,10; //esp减去10,就在堆栈上腾出了10个字节的空间给变量buf(也可能为了对
//齐对多分配几个字节)。
等到程序执行到这里的时候才在栈上为其开辟一块空间。
函数结束回收时只要将esp的值恢复到之前的值就等于释放了这部分内存。
比如:
push ebp
mov ebp,esp //原始esp保存起来
sub esp,0xA
//....
mov esp,ebp //函数结束,恢复esp
pop ebp //恢复ebp
堆内存是动态分配,程序运行时才能确定分配的地址。
注意!栈空间是静态分配的并不代表栈里的局部变量是静态分配的!静态分配内存的方式并不是指编译的时候分配,而是指在程序加载到内存后在主函数main()调用之前分配!对于变量,也即应该只有static、全局变量的内存是静态分配的。