Go语言中runtime.deferreturn是否会被调用?基于汇编代码的疑问
关于Go函数中defer对应汇编代码的疑问
我在查看包含defer的Go函数末尾的汇编代码时,看到如下内容:
0x000000000047e1a0 <+256>: callq *%rsi 0x000000000047e1a2 <+258>: movb $0x0,0x7(%rsp) 0x000000000047e1a7 <+263>: mov 0x748(%rsp),%rdx 0x000000000047e1af <+271>: mov (%rdx),%rbx 0x000000000047e1b2 <+274>: callq *%rbx 0x000000000047e1b4 <+276>: mov 0x750(%rsp),%rbp 0x000000000047e1bc <+284>: add $0x758,%rsp 0x000000000047e1c3 <+291>: retq 0x000000000047e1c4 <+292>: callq 0x42ea40 <runtime.deferreturn> 0x000000000047e1c9 <+297>: mov 0x750(%rsp),%rbp 0x000000000047e1d1 <+305>: add $0x758,%rsp 0x000000000047e1d8 <+312>: retq 0x000000000047e1d9 <+313>: callq 0x458900 <runtime.morestack>
可以看到,调用runtime.deferreturn之前存在一条retq指令,因此看起来该函数永远不会被调用。请问我的理解是否正确?
你的理解不正确,runtime.deferreturn会被正常调用
原因如下:
- Go编译器会为带defer的函数,在所有可能的退出路径都插入
runtime.deferreturn的调用逻辑,包括正常return、panic恢复后的退出等场景。你看到的<+291>处的retq只是函数的常规退出分支,并非唯一路径。 - 当函数因panic触发栈展开、或者通过某些异常分支跳转时,程序会执行到
<+292>位置的runtime.deferreturn调用,用来执行所有注册的defer函数。 - 另外,
<+313>处的runtime.morestack是栈扩容处理逻辑,当函数运行中需要扩展栈空间时,会跳转到这里执行,处理完成后也可能回到runtime.deferreturn的执行路径。 - Go编译器会做defer优化,但只要函数里声明了defer,就一定会在对应场景下触发
runtime.deferreturn,不会出现永远不调用的情况。
内容的提问来源于stack exchange,提问作者linlin
相关产品推荐
相关产品推荐

