user-0 提问: 运行时可以动态增大进程栈空间吗？

回复:
user: user-0
content: 我也知道栈溢出，但是我觉得也可能那是在没有分配栈空间的情况下而使用了未定义的内存空间，或覆盖了进程其它数据，但如果分配了合法的内存空间（不会与进程或系统其它数据冲突）作为栈空间，是不是就不会栈溢出呢？

user: user-1
content: 我认为不可以，否则栈溢出就不会是问题。

user: user-0
content: 谢谢大家，基本理解了！！！

user: user-2
content: 引用 15 楼 chenhui1990421 的回复:[quote=引用 13 楼 jerry_dqh 的回复:] [quote=引用 10 楼 chenhui1990421 的回复:] 栈在物理内存中是连续的吗？ 对于一些程序，都是讲线性空间。[/quote] 所谓的线性空间可以理解成虚拟内存吗？[/quote] 不可以，对于32位系统，你的进程启动后，OS会给你的进程分配4G的线性空间，与其他的进程是独立开来的。当你的程序用到线性地址中的某块，操作系统才会将真实的物理内存映射到线性空间，所以当在程序了使用连续的地址，实际上用的是线性地址。操作系统可能将不连续的物理内存映射到进程中连续的线性地址中。对于程序来说感应不到真实的物理的地址是否连续了。

user: user-0
content: 引用 13 楼 jerry_dqh 的回复:[quote=引用 10 楼 chenhui1990421 的回复:] 栈在物理内存中是连续的吗？ 对于一些程序，都是讲线性空间。[/quote] 所谓的线性空间可以理解成虚拟内存吗？

user: user-0
content: 《windows核心编程》上说物理内存始终都以页面为单位来调拨，这是不是意味着所有的长度大于4kb的程序模块都可能不是连续的？

user: user-2
content: 引用 10 楼 chenhui1990421 的回复:栈在物理内存中是连续的吗？ 对于一些程序，都是讲线性空间。

user: user-3
content: 另外API会从用户态进入内核态，一定会使用内核堆栈，和用户堆栈两个堆栈，自然也不会物理一定连续了。 一般都不会物理连续的

user: user-3
content: 引用 10 楼 chenhui1990421 的回复:栈在物理内存中是连续的吗？ 未必，你看到我上面的代码了吗， main 函数有两个不同的堆栈 这个一定不会是必然连续的了。 即使一个堆栈，通常都是使用虚拟内存，的物理上一般不连续。  多线程程序，每个程序有多个堆栈； 这些堆栈虚拟地址，也不是连续的； 物理地址上，自然一般不连续。

user: user-0
content: 栈在物理内存中是连续的吗？

user: user-3
content: 引用 7 楼 supermegaboy 的回复:通常需要很大栈空间的行为属于设计错误。 ++

user: user-3
content: 上面的堆栈设置有点错误。 这个是测试过的没问题的。  int const NewSize =1024*1024 *8 /sizeof(int);//8M int run(){      int a[NewSize/2]={0}; 	for(int i=0;i<NewSize/2;i++)a[i] = i; 	printf("address of a = %p,address of a[NewSize/2-1]=%p,  %d\n",a,&a[NewSize/2-1],a[NewSize/2-1]);     return a[NewSize/2-1] ; }  int main(int argc, char* argv[]) {  	static int esp_sav = 0; 	static int ebp_sav = 0; 	static int *stack = new int[NewSize]; 	static int *top   = stack + NewSize -1; 	int a[200]={0};	 	printf("address of a = %p,address of a[100]=%p,  %d\n",a,&a[100],a[100]); 	printf("stack = %p,top =%p \n",stack,top);      	__asm{ 		mov esp_sav,esp 		mov ebp_sav,ebp 		mov esp,top 		mov ebp,esp	 	}  	{ 		printf("%d\n",run()); 		printf("%p\n",esp_sav); 	} 	 	__asm{ 		mov esp,esp_sav 		mov ebp,ebp_sav 	}     delete []stack;  	printf("Hello World!\n"); 	return 0; }

user: user-4
content: 通常需要很大栈空间的行为属于设计错误。

user: user-5
content: 有操作系统支持栈的自动增长的。 平坦模式的os可能有点困难；段模式的os应该比较容易实现。

user: user-6
content: 动态增大栈？没听过，一般都是在事先设置好的。一般没必要用那么大的栈吧，除非递归什么的。不过递归也不建议调大栈空间吧。 动态分配（堆）要说极限的话，逻辑上的问题一般，都是有操作系统来处理的，不一定有多少空间就一定会分配，比如有内存碎片什么的导致空间浪费，硬件上的话，主要还是硬件本身能提供多少的问题吧。

user: user-3
content: 举例：  #include <iostream>  using namespace std;  int a[4][4]={0,1,2,3,}; int firstElem(int a[][4]){  return a[0][0]; } int run(){ cout << firstElem(a)<<",Hello world!" << endl;}; int main() {     static int esp_sav =0;     static int ebp_sav =0;     static char * stack =new char [1024*1024*8];//设置为8M     __asm {         mov esp_sav,esp          mov ebp_sav,ebp                  mov esp ,stack         mov ebp ,esp      }           {            run();     }      __asm {         mov esp,esp_esp          mov ebp,ebp_sav       }     delete []stack ;     return 0; } PS： 这种情况下，异常不好处理。 一般都不会这个干的。

user: user-3
content: Windows 堆栈空间是属于线程的； Win32 不做任何处理的话，分配默认大小空间(1M 或者2M)； 但是提交很少的内存，随着堆栈空间的增长，逐渐提交，直到用完或者溢出。  如果手动控制的话，可以重新设置新的堆栈的指针，那么堆栈大小就是用户分配的大小。 在函数返回时要恢复堆栈指针，没有恢复之前，不能产生未处理异常。  不过几乎没有代码。手动设置堆栈指针。 这样堆栈的大小是固定的，不过提交的页面是可以动态增加的。  堆栈默认大小，可以在编译时设置，也有预编译指令可以设置，设置的大小也是固定的。