Go语言的函数调用栈

9 篇文章 0 订阅
9 篇文章 0 订阅

函数栈帧

  • 我们知道,Golang可以把程序直接编译成.exe可执行文件,运行时,可执行文件被加载到内存,这些个机器指令对应到虚拟地址空间中,位于代码段(虚拟地址空间分别有:栈、堆、数据段、代码段)。
  • 在这其中,如果在一个函数调用另一个函数,编译器就会对应生成一条call指令,每个函数最后都有一条ret指令,负责函数结束后跳回到调用处
  • 函数执行时,需要有足够的空间存放局部变量、参数、返回值等信息,这段空间对应虚拟地址空间中的。分配给函数的空间叫做函数栈帧,这就是咱们的主角了。栈底通常叫栈基bp,栈顶又叫栈指针sp,整个栈帧中(仅谈Golang),从底到顶依次为:栈基、局部变量,返回值、参数、栈指针

call与ret

call指针只做两件事:
  • 将下一条指令入栈,即返回地址,被调用函数执行结束后可直接跳回这里继续执行
  • 跳转到被调用函数入口处开始执行(被调用者是通过栈指针sp+偏移找到对应指令进行执行的)
ret指令同样做两件事:
  • 弹出返回地址
  • 跳转到返回地址

defer与返回值

  • 返回值赋值defer谁先谁后呢?答:先给返回值赋值,再执行defer函数。
  • 如果返回值是匿名类型func Method() int {},Golang的函数栈帧中返回值是用来存放其值result的,即使return a,也相当于将a的值拷贝给返回值resultresult = a,所以再defer中对a进行操作,是不会影响返回值result的结果的。
  • 如果返回值是已命名类型func Method() (a int) {},则就相当于对函数栈帧中返回值这一空间重新命名了,这时候你在defer中操作这个a,是会影响最终的返回结果的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值