为什么在src / runtime / proc.go的主要功能中似乎没有用的无限for循环?

Today I came across a post asking about this question. At the end of the main function in src/runtime/proc.go there is a seemingly useless infinite for loop. Why is it there?

source code link

    if atomic.Load(&panicking) != 0 {
        gopark(nil, nil, waitReasonPanicWait, traceEvGoStop, 1)
    }

    exit(0)
    for {
        var x *int32
        *x = 0
    }
dtnnpt11795
dtnnpt11795 从移动设备链接群组非常困难,这是正确的链接:groups.google.com/d/msg/golang-nuts/FnF3oZeJ7aY/sLz0G3oDAgAJ
一年多之前 回复
duanbozhong9689
duanbozhong9689 groups.google.com/forum/m/#!topic/golang-nuts/FnF3oZeJ7aY
一年多之前 回复

1个回答

Assigning 0 to a protected memory region e.g. *(*int)(nil) = 0 and *x = 0 in systems with memory protection unit causes segmentation fault and stops the programme,
And in systems without memory protection unit, just writes 0 to the memory address at zero and nothing happens so they added a for loop to stop the programme (CPU) there.

  1. Normally it is (should be) unreachable code.

  2. File: ~/go/src/runtime/proc.go at the end of func main():

    exit(0)
    for {
        var x *int32
        *x = 0
    }

ref:

The runtime is a special case in many ways, and this is among the more special parts. This loop exists to catch problems while testing new ports. If that loop is ever reached, something has gone badly wrong: the exit call should have caused the program to exit. We can't assume that panic is working. We can't really assume that anything is working. What we want to do is stop the program. Since exit failed, it's possible that a nil dereference will succeed. If that fails too, we still have to do something, so we just loop. We can't return because this is the main function that started the program; there is nothing to return to.


  1. Also Calling panic("err msg") here inside /usr/local/go/src/runtime/panic.go at the end of func fatalpanic(msgs *_panic) has unreachable code:
    systemstack(func() {
        exit(2)
    })

    *(*int)(nil) = 0 // not reached
}

  1. Here var x *int: x is a nil pointer, so *x = 0 is a panic: runtime error: invalid memory address or nil pointer dereference and causes segmentation violation:
package main

func main() {
    var x *int
    *x = 0
}

Output:

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x44f972]

  1. Here for test propose to generated a panic and recover:
    File ~/go/src/internal/x/crypto/cryptobyte/cryptobyte_test.go
func TestGeneratedPanic(t *testing.T) {
    defer func() {
        recover()
    }()

    var b Builder
    b.AddUint8LengthPrefixed(func(b *Builder) {
        var p *byte
        *p = 0
    })

    t.Error("Builder did not panic")
}

  1. File ~/go/src/cmd/compile/internal/gc/subr.go:
func hcrash() {
    if Debug['h'] != 0 {
        flusherrors()
        if outfile != "" {
            os.Remove(outfile)
        }
        var x *int
        *x = 0
    }
}
  1. File ~/go/pkg/bootstrap/src/bootstrap/cmd/compile/internal/gc/subr.go:
func hcrash() {
    if Debug['h'] != 0 {
        flusherrors()
        if outfile != "" {
            os.Remove(outfile)
        }
        var x *int
        *x = 0
    }
}

Which is called here ~/go/src/cmd/compile/internal/gc/subr.go at the end of:


func Fatalf(fmt_ string, args ...interface{}) {
    flusherrors()

    if Debug_panic != 0 || nsavederrors+nerrors == 0 {
        fmt.Printf("%v: internal compiler error: ", linestr(lineno))
        fmt.Printf(fmt_, args...)
        fmt.Printf("
")

        // If this is a released compiler version, ask for a bug report.
        if strings.HasPrefix(objabi.Version, "go") {
            fmt.Printf("
")
            fmt.Printf("Please file a bug report including a short program that triggers the error.
")
            fmt.Printf("https://golang.org/issue/new
")
        } else {
            // Not a release; dump a stack trace, too.
            fmt.Println()
            os.Stdout.Write(debug.Stack())
            fmt.Println()
        }
    }

    hcrash()
    errorexit()
}

  1. Following code panics here inside /usr/local/go/src/runtime/panic.go at the end of func fatalpanic(msgs *_panic):
    systemstack(func() {
        exit(2)
    })

    *(*int)(nil) = 0 // not reached
}

Code to panic! (similar to Calling panic("err msg"):

package main

import (
    "fmt"
    "math/rand"
)

func main() {
    r := rand.Rand{}
    i := r.Int()
    fmt.Println(i)
}

Output:

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0xffffffff addr=0x0 pc=0xd8276]

goroutine 1 [running]:
math/rand.(*Rand).Int63(...)
    /usr/local/go/src/math/rand/rand.go:85
math/rand.(*Rand).Int(...)
    /usr/local/go/src/math/rand/rand.go:103
main.main()
    /tmp/sandbox449835614/main.go:10 +0x36
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问
相关内容推荐