g._defer.fn 不能影响 runtime.gopanic 中的 g._defer?

问题描述 投票:0回答:0

我对runtime.gopanic

部分
感到困惑。下面是我的测试 golang 代码和它的
plan9
编译。

package main

func main() {
    a := func() {
        b := func() {
            recover()
        }
        defer b()
    }
    defer a()
    panic(1)
}

        main.go:3       0x105a100       493b6610        cmp rsp, qword ptr [r14+0x10]
        main.go:3       0x105a104       7651            jbe 0x105a157
=>      main.go:3       0x105a106*      4883ec68        sub rsp, 0x68
        main.go:3       0x105a10a       48896c2460      mov qword ptr [rsp+0x60], rbp
        main.go:3       0x105a10f       488d6c2460      lea rbp, ptr [rsp+0x60]
        main.go:4       0x105a114       488d0dc50e0100  lea rcx, ptr [rip+0x10ec5]
        main.go:4       0x105a11b       48894c2458      mov qword ptr [rsp+0x58], rcx
        main.go:10      0x105a120       48894c2428      mov qword ptr [rsp+0x28], rcx
        main.go:10      0x105a125       488d442410      lea rax, ptr [rsp+0x10]
        main.go:10      0x105a12a       e89136fdff      call $runtime.deferprocStack
        main.go:10      0x105a12f       85c0            test eax, eax
        main.go:10      0x105a131       7515            jnz 0x105a148
        main.go:10      0x105a133       eb00            jmp 0x105a135
        main.go:11      0x105a135       488d05043f0000  lea rax, ptr [rip+0x3f04]
        main.go:11      0x105a13c       488d1d8d3a0100  lea rbx, ptr [rip+0x13a8d]
        main.go:11      0x105a143       e83847fdff      call $runtime.gopanic
        main.go:10      0x105a148       e8533cfdff      call $runtime.deferreturn
        main.go:10      0x105a14d       488b6c2460      mov rbp, qword ptr [rsp+0x60]
        main.go:10      0x105a152       4883c468        add rsp, 0x68
        main.go:10      0x105a156       c3              ret
        main.go:3       0x105a157       e8c4cfffff      call $runtime.morestack_noctxt
        .:0             0x105a15c       eba2            jmp $main.main

在golang中,

defer
会调用
runtime.deferprocStack
,这样当前的
g._defer
应该指向最里面的defer。
panic
会打电话给
runtime.gopanic
.

在我的测试代码中,调用

runtime.gopanic
时,当前的
g._defer.fn
main.a
。就像这样:

g._defer = &_defer{ fn: `main.a`, link: nil }

所以在panic.go:918中,

main.a()
会被执行,而在
main.a
中,另一个fn为
_defer
main.a.b
会被g._defer指向,之前的
defer
会赋值给这个一个
link
。就像这样:

g._defer = &_defer{ fn: `main.a.b`, link: &_defer{ fn: `main.a`, link: nil } }

Howerer,在 panic.go:923 中,

gp._defer != d
仍然是正确的。我是不是在整个过程中忽略了什么?

我用

dlv
调试我的代码,我的golang版本是1.18.3

我真的很想知道原因,如果你能解释一下,我真的很感激!

go runtime deferred
© www.soinside.com 2019 - 2024. All rights reserved.