Skip to content

Panic and crash cases

Go101 edited this page Jan 15, 2020 · 16 revisions

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

  • An interger value is divided by zero.
  • Nil dereference:
  • Index out of range.
    • Index out of range when indexing array/slice elements.
    • Index out of range when deriving slices from arrays/slices.
  • Type assertion failed but only one return result is presented.
  • Comparing interface values with the same incomparable dynamic type.
  • Using interface value with incomparable dynamic types as map keys.
  • Sending values to or closing closed channels.
  • On 32-bit OS, applying 64 bit atomic operations on non-8-bytes aligned words.
  • ... (more? Welcome everybody to improve this list.)

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!
  • Modify immutable memory zone (mainly through unsafe ways. See the last example below.).
  • No goroutines (main called runtime.Goexit) - deadlock!

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)
}
Clone this wiki locally
You can’t perform that action at this time.