现实世界中,到处都有堆栈的影子,任何堆叠的东西,例如盘子堆叠、书籍堆叠等等。
堆栈的历史起源
- 堆栈的起源可以追溯到1946年,当时Alan M. Turing在计算机科学文献中使用术语“bury”和“unbury”作为调用子程序和从子程序返回的方式。
- 1955年,慕尼黑工业大学的Klaus Samelson和Friedrich L. Bauer提出了一种名为Operationskeller(英语“操作地窖”)的堆栈的想法。
- 1988年,Klaus Samelson因发明堆栈原理而获得了IEEE计算机先锋奖。
- 以上内容来自维基百科。
堆栈地址
熟悉程序执行的可能会认为,同一个程序每次运行从统一的地址开始,包括堆栈数据也会跟着确定。事实上,这种方式很容易被攻击。ASLR技术让每次运行地址都可以随机。
int main()
{
int a;
printf("%p\n", &a);
return 0;
}
堆栈大小
- 不同操作系统、编程语言或编译器有不同堆栈默认值,除非特别指出。
- 内核态和用户态是不同堆栈,堆栈大小也不同。
- Java 8之前提供-Xss选项设定,例如-Xss128k,Java 8之后使用-Xoss=<init_size> -XX:ThreadStackSize=<max_size>设定。
- Windows内核模式堆栈的大小限制为大约三个page, 用户模式堆栈默认为1MB(通过设置链接属性更改)。
变量的存储位置
- C/C++局部变量默认在堆栈中,不管是基本类型、C++对象均是如此。
- Java/C#的对象实行统一化管理,默认存放在堆中,函数局部变量默认引用堆对象,此局部变量依然存放在堆栈中,和C++局部变量对象指针类似。