英文:
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?
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论