gpt4 book ai didi

go - 为什么src/runtime/proc.go中的main函数中有一个看似无用的无限for循环?

转载 作者:IT王子 更新时间:2023-10-29 02:07:07 24 4
gpt4 key购买 nike

今天看到一个帖子问这个问题。在 src/runtime/proc.go 的 main 函数的末尾有一个看似无用的无限循环。为什么会在那里?

source code link

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

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

最佳答案

0 分配给 protected 内存区域,例如*(*int)(nil) = 0*x = 0在带有 memory protection unit 的系统中原因segmentation fault并停止程序,
在没有内存保护单元的系统中,只需将 0 写入零处的内存地址,什么也不会发生,因此他们添加了一个 for 循环来停止那里的程序 (CPU)。

  1. 通常它是(应该是)无法访问的代码

  2. 文件:~/go/src/runtime/proc.gofunc 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. 还在 func 末尾的 /usr/local/go/src/runtime/panic.go 中调用 panic("err msg") fatalpanic(msgs *_panic)无法访问的代码:
    systemstack(func() {
exit(2)
})

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

  1. 这里var x *int:x是一个nil指针,所以*x = 0是一个 panic :运行时错误:无效的内存地址或零指针取消引用并导致分段违规:
package main

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

输出:

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

  1. 此处用于测试建议生成 panic 并恢复:
    文件 ~/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. 文件 ~/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. 文件 ~/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
}
}

这里调用的是 ~/go/src/cmd/compile/internal/gc/subr.go 结尾处:


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("\n")

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

hcrash()
errorexit()
}

  1. 以下代码在 /usr/local/go/src/runtime/panic.go 中的代码在 func fatalpanic(msgs *_panic) 的末尾发生 panic:<
    systemstack(func() {
exit(2)
})

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

Code to panic! (类似于调用 panic("err msg"):

package main

import (
"fmt"
"math/rand"
)

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

输出:

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

关于go - 为什么src/runtime/proc.go中的main函数中有一个看似无用的无限for循环?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55416148/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com