Назначение 0
защищенной области памяти, например *(*int)(nil) = 0
и *x = 0
в системах с блок защиты памяти вызывает ошибка сегментации и останавливает программу,
А в системах без модуля защиты памяти просто записывает 0
по адресу памяти в ноль и ничего не происходит, поэтому они добавили цикл for для остановки программы (ЦП) там.
Обычно это (должно быть) недоступный код .
Файл: ~/go/src/runtime/proc.go
в конце func main()
:
exit(0)
for {
var x *int32
*x = 0
}
исх
Время выполнения - это особый случай во многих отношениях, и это один из
специальные части. Этот цикл существует для обнаружения проблем при тестировании новых
порты. Если этот цикл когда-либо достигнут, что-то пошло не так:
вызов на выход должен был вызвать выход из программы. Мы не можем предположить
эта паника работает. Мы не можем предположить, что что-то
за работой. Что мы хотим сделать, это остановить программу. Так как выход не состоялся,
Вполне возможно, что разыменование будет успешным. Если и это не поможет,
нам еще нужно что-то делать, поэтому мы просто зацикливаемся. Мы не можем вернуться
потому что это основная функция, которая запустила программу; есть
нечего возвращаться
- Также звонит
panic("err msg")
здесь, внутри /usr/local/go/src/runtime/panic.go
, в конце func fatalpanic(msgs *_panic)
имеет недоступный код :
systemstack(func() {
exit(2)
})
*(*int)(nil) = 0 // not reached
}
- Здесь
var x *int
: x
- указатель nil
, поэтому *x = 0
- паника: ошибка времени выполнения: неверный адрес памяти или разыменование нулевого указателя и вызывает нарушение сегментации:
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]
- Здесь для теста предложите сгенерировать панику и восстановиться:
Файл ~/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")
}
- Файл
~/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
}
}
- Файл
~/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()
}
- Следующий код паникует здесь, внутри
/usr/local/go/src/runtime/panic.go
в конце func fatalpanic(msgs *_panic)
:
systemstack(func() {
exit(2)
})
*(*int)(nil) = 0 // not reached
}
Код для паники! (похоже на Звонок 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