panic () stacktrace tidak menampilkan parameter fungsi

Sep 07 2020

Pada kode di bawah ini:

package main
    
func main() {
    example(make([]string, 2, 4), "hello", 10)
}
    
func example(slice []string, str string, i int) {
    panic("Want stack trace")
}

6 kata digunakan untuk menyimpan data dan meneruskan ke fungsi example.

  • 3 kata untuk sliceheader
  • 2 kata untuk strstring
  • satu kata untuk iinteger

Pelacakan tumpukan yang diharapkan:

goroutine 1 [running]:
main.example(0xc000042748, 0x2, 0x4, 0x106abae, 0x5, 0xa)
    stack_trace/example1/example1.go:13 +0x39
main.main()
    stack_trace/example1/example1.go:8 +0x72
    
// Declaration
main.example(slice []string, str string, i int)
    
// Call
make([]string, 2, 4), "hello", 10
    
// Values (0xc000042748, 0x2, 0x4, 0x106abae, 0x5, 0xa)
Slice Value:   0xc000042748, 0x2, 0x4
String Value:  0x106abae, 0x5
Integer Value: 0xa

Pelacakan tumpukan sebenarnya:

panic: Want stack trace
    
goroutine 1 [running]:
main.example(...)
        /home/../Main.go:8
main.main()
        /home/../Main.go:4 +0x39
exit status 2

$ go version
go version go1.14.3 linux/amd64

Mengapa stacktrace yang dihasilkan panic()tidak menampilkan 6 kata tersebut?

Jawaban

5 Marc Sep 08 2020 at 06:11

Go ditampilkan main.example(...)karena fungsinya sebaris oleh compiler dan tidak ada lagi sebagai fungsi, sudah disematkan di dalamnya main()(detail logika pencetakan ada di traceback.go ).

Anda dapat memberi tahu compiler untuk tidak menyebariskan fungsi dengan menggunakan go:noinline direktif compiler :

//go:noinline
func example(slice []string, str string, i int) {
  panic("Want stack trace")
}

Dengan menonaktifkan sebaris, keluaran pelacakan balik default ditampilkan main.exampledan parameternya:

panic: Want stack trace

goroutine 1 [running]:
main.example(0xc000046738, 0x2, 0x4, 0x473f27, 0x5, 0xa)
    /home/me/stuff/src/github.com/me/testing/panic/main.go:9 +0x39
main.main()
    /home/me/stuff/src/github.com/me/testing/panic/main.go:4 +0x72

Catatan yang maketidak muncul di pelacakan tumpukan, juga tidak bisa: itu telah dikembalikan sebelum panicpernah tercapai.

Sebuah kata nasihat : go:noinlinedigunakan di sini untuk menunjukkan mengapa jejak tumpukan tidak berisi argumen fungsi. Seseorang seharusnya tidak memaksakan keputusan pengoptimalan compiler kecuali melakukan debug pada compiler atau berurusan dengan fungsi runtime yang membutuhkannya.