Skip to content

Panic and crash cases

Go101 edited this page Jun 19, 2021 · 21 revisions
Clone this wiki locally

For the standard Go compiler, the following cases will cause run-time recoverable panics (some of them might be compiler dependent):

Crash cases, or fatal unrecoverable errors (some of them might be compiler dependent):

  • Using nil function values as goroutine start functions.
  • Stack overflow (dead loop, etc).
  • Out of memory when allocating memory.
  • Segmentation violation (generally by using unsafe.Pointer wrongly).
  • Concurrent map read and map write detected.
  • All goroutines are asleep - deadlock!
  • A goroutine exceeds the MaxStack limit while growing its stack.
  • Modify immutable memory zone (mainly through unsafe ways. See the last example below.).
  • No goroutines (main called runtime.Goexit) - deadlock!
  • When data race detector compiler dynamic analysis option is used, many data race cases will be detected at run time. Once a data race is detected, program crashes.
  • Set finalizer for an address twice.

An example for the last crash case:

package main

import (
	"runtime"
	"time"
)

func main() {
	go func() {
		time.Sleep(time.Second)
	}()
	
	runtime.Goexit()
}

An example of modifying immutable memory zone:

package main

import (
	"fmt"
	"strings"
	"unsafe"
)
var _ = strings.Join

type SliceHeader struct {
	Data unsafe.Pointer
	Len  int
	Cap  int
}

type StringHeader struct {
	Data unsafe.Pointer
	Len  int
}

func String2ByteSlice(str string) (bs []byte) {
	strHdr := (*StringHeader)(unsafe.Pointer(&str))
	sliceHdr := (*SliceHeader)(unsafe.Pointer(&bs))
	sliceHdr.Data = strHdr.Data
	sliceHdr.Len = strHdr.Len
	sliceHdr.Cap = strHdr.Len

	return
}

//var Golang = strings.Join([]string{"Go", "lang"}, "") // not cause panicking
var Golang = "Golang"                                   // causes panicking

func main() {
	var goland = String2ByteSlice(Golang)
	goland[5] = 'd' // fatal error: unexpected fault address
	fmt.Printf("%s\n", goland)
}