panic () stacktrace не показывает параметры функции

Sep 07 2020

В приведенном ниже коде:

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

6 слов используются для хранения данных и передачи их функции example.

  • 3 слова для sliceзаголовка
  • 2 слова для strстроки
  • одно слово для iцелого числа

Ожидаемая трассировка стека:

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

Фактическая трассировка стека:

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

Почему на трассировке стека panic()не отображаются эти 6 слов?

Ответы

5 Marc Sep 08 2020 at 06:11

Go отображается, main.example(...)потому что функция встроена компилятором и больше не существует как функция, она встроена в main()(подробности логики печати находятся в traceback.go ).

Вы можете указать компилятору не встраивать функцию , используя go:noinline директиву компилятора :

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

Если встраивание отключено, вывод трассировки по умолчанию показывает main.exampleи его параметры:

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

Обратите внимание, что makeэто не отображается в трассировке стека и не может: оно было возвращено до того, panicкак будет достигнуто.

Небольшой совет : go:noinlineздесь используется, чтобы показать, почему трассировка стека не содержит аргументов функции. Как правило, не следует форсировать решения по оптимизации компилятора, кроме случаев отладки компилятора или работы с функциями времени выполнения, которые в этом нуждаются.