编程语言 · 2023年 10月 27日 0

堆栈

56 次浏览

现实世界中,到处都有堆栈的影子,任何堆叠的东西,例如盘子堆叠、书籍堆叠等等。

堆栈的历史起源

  • 堆栈的起源可以追溯到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++局部变量对象指针类似。