方法栈

2026-10-16 14:32:57 计算机底层

有没有想过,主函数在执行时,计算机底层是如何保证执行顺序的?嵌套调用的函数,又是怎么维持调用次序的?

在各类语言的底层,函数执行顺序依靠调用栈来保障。每一次函数调用都会生成一个栈帧,栈帧保存着函数运行的关键信息:

第一,返回地址,也就是上一层调用指令的地址;

第二,参数,返回值的存储空间。

每次函数执行完毕后,上层就可以从这个空间拿到当前函数的执行结果,回到上一层继续执行。

前面提到栈里保存的返回地址,是第二层保障。栈的设计,让 CPU 只需要关注栈顶,不用维护复杂的调用链;真正的执行顺序,在压栈的过程中就已经确定好了。

每次方法的调用都会产生一个栈帧,一个函数能拥有多个栈帧

来看一个简单的案例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
func c(n int) int {
return n * 2
}

func b(n int) int {
return c(n) + 1
}

func a(n int) int {
return b(n) + 100
}

func main() {
x := a(5)
println(x)
}
Text
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
时间 →   main    a      b      c
│
├─调用 a ──────►
│ │
│ ├─调用 b ─────►
│ │ │
│ │ ├─调用 c ──►
│ │ │ │
│ │ │ ├ return 10
│ │ ├◄──────────┘
│ │ │ 算出 11
│ ├◄─────────────┘
│ │ 算出 111
├◄─────────────┘
│ x=111
▼

栈深度: 1 2 3 4 (最深)
←──── 增长 ────→
←──── 收缩 ────→
Text
1
2
3
4
5
6
7
8
9
10
11
低地址(栈顶)
┌─────────────────────┐
│ c 的栈帧 │ ← 最后调用
├─────────────────────┤
│ b 的栈帧 │
├─────────────────────┤
│ a 的栈帧 │
├─────────────────────┤
│ main 的栈帧 │ ← 最先调用,栈底
└─────────────────────┘
高地址(栈底)