How to trace/track/profile/capture/break "runtime error: invalid memory address or nil pointer dereference"?

huangapple go评论90阅读模式
英文:

How to trace/track/profile/capture/break "runtime error: invalid memory address or nil pointer dereference"?

问题

有没有一种方法可以确定这些神秘的“运行时错误:无效的内存地址或空指针解引用消息”来自哪里?

我尝试在各个地方设置断点,但没有运气。它不是来自我的任何日志记录 - 可能来自某个第三方库。

我还尝试了log.SetFlags(LstdFlags|Llongfile),但没有改变任何冗长度。

我记得在其他一些语言和调试器中,总有一种方法可以找出何时发生分段错误或空指针引用异常。对于Golang是否有这样的魔法?

谢谢!

英文:

is there a magic to identify where these mystery runtime error: invalid memory address or nil pointer dereference messages come from?

How to trace/track/profile/capture/break "runtime error: invalid memory address or nil pointer dereference"?

I tried setting breakpoint everywhere but no luck. It's not from any of my loggings - probably from some 3rd party library.

I also tried log.SetFlags(LstdFlags|Llongfile) but doesn't change any verbosity.

I remember in some other languages + debugger there is always a way to find out when segmentation fault or null pointer reference exception takes place. Is there such magic for Golang?

Thanks!

答案1

得分: 2

请注意,我将为您翻译以下内容:

参见defer、panic和recover的Go博客。

在运行延迟函数时,如果延迟是作为对panic的反应而执行的,堆栈仍然包含panic时的状态:

func withTrace() {
	defer func() {
		if r := recover(); r != nil {
			fmt.Printf("caught panic: %s\n", r)
			var stack [4096]byte
			n := runtime.Stack(stack[:], false)
			fmt.Printf("%s", stack[:n])
			fmt.Println("\n// notice how 'trigger()' appears in the stack trace above,\n// even though the 'defer' is called from 'withTrace()'")
		}
	}()

	fmt.Println("=== running withTrace() ...")
	trigger()
}

// Output:
=== running withTrace() ...
caught panic: from trigger
goroutine 1 [running]:
main.withTrace.func1()
	/tmp/sandbox2519976531/prog.go:31 +0x8b
panic({0x48a120, 0x4b8c60})
	/usr/local/go-faketime/src/runtime/panic.go:884 +0x212
main.trigger(...)
	/tmp/sandbox2519976531/prog.go:11
main.withTrace()
	/tmp/sandbox2519976531/prog.go:38 +0x8c
main.main()
	/tmp/sandbox2519976531/prog.go:43 +0x1c

// notice how 'trigger()' appears in the stack trace above,
// even though the 'defer' is called from 'withTrace()'

https://go.dev/play/p/MOapLmcSVVt


您需要在执行处理程序的函数序列中的某个位置调用recover()

在一个HTTP服务器中,如果您想追踪处理程序中的每个可能的panic,一个好的位置是在所有路由上设置一个中间件。

英文:

See defer, panic and recover on the go blog.

When running a deferred function, if the defer is executed in reaction to a panic, the stack still contains the state at panic time :

func withTrace() {
	defer func() {
		if r := recover(); r != nil {
			fmt.Printf("caught panic: %s\n", r)
			var stack [4096]byte
			n := runtime.Stack(stack[:], false)
			fmt.Printf("%s", stack[:n])
			fmt.Println("\n// notice how 'trigger()' appears in the stack trace above,\n// even though the 'defer' is called from 'withTrace()'")
		}
	}()

	fmt.Println("=== running withTrace() ...")
	trigger()
}

// Output:
=== running withTrace() ...
caught panic: from trigger
goroutine 1 [running]:
main.withTrace.func1()
	/tmp/sandbox2519976531/prog.go:31 +0x8b
panic({0x48a120, 0x4b8c60})
	/usr/local/go-faketime/src/runtime/panic.go:884 +0x212
main.trigger(...)
	/tmp/sandbox2519976531/prog.go:11
main.withTrace()
	/tmp/sandbox2519976531/prog.go:38 +0x8c
main.main()
	/tmp/sandbox2519976531/prog.go:43 +0x1c

// notice how 'trigger()' appears in the stack trace above,
// even though the 'defer' is called from 'withTrace()'

https://go.dev/play/p/MOapLmcSVVt


You would have to place this call to recover() somewhere in the sequence of functions that execute your handlers.

In an http server, if you want to trace every possible panic in your handlers, a good place is a middleware set on all routes.

huangapple
  • 本文由 发表于 2022年9月29日 11:34:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/73890004.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定