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

#go

#Вперед

Вопрос:

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

 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
  

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

Комментарии:

1. Обычно ли трассировки стека включают значения переменных? Я этого раньше не видел. Если вы хотите реализовать это самостоятельно, вы можете захватить стек с помощью golang.org/pkg/runtime/debug/#Stack а затем также выведите значения.

2. Я думаю, вы ищете время выполнения. SetTraceback()

Ответ №1:

Отображается 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 здесь используется, чтобы показать, почему трассировка стека не содержит аргументов функции. Как правило, не следует форсировать решения по оптимизации компилятора, если не выполняется отладка компилятора или работа с функциями среды выполнения, которые в этом нуждаются.

Комментарии:

1. Что означает «функция встроена компилятором»?

2. Ожидаемая трассировка стека также имеет make() вызов. Это также считается встроенным? Фактическая трассировка стека этого не показывает.

3. Почему make это должно быть там? Это не вызов panic , это вызвано и вернулось раньше panic .