Rus*_*ist 10
我不能代表所有平台,但事实上,我只是花了一些时间使用Windows .exe文件(我的意思是,实际上研究它们的二进制格式 - 我知道在某种意义上我们所有人在这里工作可执行文件;)).我敢打赌大多数其他平台都有类似的功能,但我并不是很熟悉它们.
部分文件格式本身包含两个与当前讨论相关的值:
typedef struct _IMAGE_OPTIONAL_HEADER {
...
DWORD SizeOfStackReserve;
DWORD SizeOfStackCommit;
...
} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;
Run Code Online (Sandbox Code Playgroud)
来自MSDN:
SizeOfStackReserve
要为堆栈保留的字节数.只有SizeOfStackCommit成员指定的内存在加载时提交; 其余部分一次可用一页,直到达到此保留金额.
SizeOfStackCommit
要为堆栈提交的字节数.
换句话说,链接器指定程序堆栈的最大大小.如果达到最大尺寸,则会溢出 - 无论您如何达到最大尺寸.你可以编写一个简单的程序,只需分配一个比最大堆栈大小更大的单个堆栈变量(比如一个数组),就可以在一行代码中完成.或者你可以通过无限(或有限但非常深)的递归来实现,或者只是通过分配太多的堆栈变量来实现.
默认情况下,Microsoft链接器在X86平台上将此值设置为1MB(在Itanium系统上为4MB).对于现代系统来说,这看起来很小.但是,更现代的Windows版本对这些值的解释略有不同.它不是完全限制堆栈,而是限制堆栈将使用的物理内存.如果您的堆栈超出此范围,虚拟内存将会涉及,所以您应该仍然很好......假设您有足够的虚拟内存.
请记住,即使在具有大量RAM和磁盘上大量虚拟内存的现代系统上,内存也可能耗尽.您只需要分配大量数据.
所以,长话短说:是否有可能在没有无限递归的情况下溢出堆栈?当然.可能吗?不是真的,除非你分配真正巨大的物体.
当堆栈指针被推出操作系统为堆栈分配的内存块时,堆栈溢出.一些操作系统会随着它的增长而调整堆栈大小(IIRC Linux会这样做),而在其他操作系统中,堆栈大小在进程或线程的开始时是固定的(IIRC Windows会这样做).
堆栈溢出的可能原因:
可能还有其他原因,我无法想到我的头脑.