我有一些 Golang 代码,非常间歇性地(每隔几个小时一次),导致 panic ,我需要一些指导来了解如何找到原因。代码是这样的(带有行号):
audio-process.go:
var MyChannel chan<- interface{}
var newDatagramList = list.New()
func operateAudioProcessing() {
var channel = make(chan interface{})
MyChannel = channel
newDatagramList.Init()
...
415 go func() {
416 for cmd := range channel {
417 switch msg := cmd.(type) {
418 case *MyThing:
419 {
420 newDatagramList.PushBack(msg)
421 }
422 }
423 }
424 }()
425 }
...在第 420 行调用
newDatagramList.PushBack()
时会发生 panic 。发送到此 channel 的代码是:audio-in.go:
thing := new(MyThing)
...
MyChannel <- thing
...并且,为了完成图片,有一个单独的定时
go func()
处理 newDatagramList
如下:go func() {
var next *list.Element
for _ = range processTicker.C {
for newElement := newDatagramList.Front(); newElement != nil; newElement = next {
next = newElement.Next();
myProcessingFunction(newElement.Value.(*MyThing))
newDatagramList.Remove(newElement)
}
}
panic 输出是:
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xb code=0x1 addr=0x0 pc=0x5702d1]
goroutine 12 [running]:
panic(0x76e520, 0xc82000e100)
/usr/lib/go-1.6/src/runtime/panic.go:481 +0x3e6
container/list.(*List).PushBack(0xc820054e40, 0x6c4f80, 0xc827294e20, 0xc8273e0b01)
/usr/lib/go-1.6/src/container/list/list.go:139 +0x1c1
main.operateAudioProcessing.func2(0xc8200164e0, 0xc82000f310, 0xc820024078, 0x240)
/home/rob/gocode/src/audio-process.go:420 +0x58b
created by main.operateAudioProcessing
/home/rob/gocode/src/audio-process.go:442 +0x5ba
panic 告诉我哪件事是错的?首先没有关于分配和发送到 channel 的提示,所以我看不出这有什么问题。
newDatagramList
显然已初始化(并且 channel 已运行并接收消息一段时间)。我如何确定是什么让我大吃一惊?
最佳答案
panic 堆栈:
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xb code=0x1 addr=0x0 pc=0x5702d1]
goroutine 12 [running]:
panic(0x76e520, 0xc82000e100)
/usr/lib/go-1.6/src/runtime/panic.go:481 +0x3e6
container/list.(*List).PushBack(0xc820054e40, 0x6c4f80, 0xc827294e20, 0xc8273e0b01)
/usr/lib/go-1.6/src/container/list/list.go:139 +0x1c1
main.operateAudioProcessing.func2(0xc8200164e0, 0xc82000f310, 0xc820024078, 0x240)
/home/rob/gocode/src/audio-process.go:420 +0x58b
created by main.operateAudioProcessing
/home/rob/gocode/src/audio-process.go:442 +0x5ba
是说在顶部列出的框架中发生了“无效的内存地址或 nil 指针取消引用”
container/list.(*List).PushBack(0xc820054e40, 0x6c4f80, 0xc827294e20, 0xc8273e0b01)
上
/usr/lib/go-1.6/src/container/list/list.go:139 +0x1c1
看起来是 from godoc
// PushBack inserts a new element e with value v at the back of list l and returns e.
func (l *List) PushBack(v interface{}) *Element {
l.lazyInit()
return l.insertValue(v, l.root.prev)
}
这很酷,因为它在这个框架中,它看起来在
l.root.prev
上出错在
container/list
上构建的数据类型是完全不同步的,并且有许多 go 例程的交错,这可能导致列表元素指针被添加同时删除的中间状态。例如
remove
有许多不同的操作:func (l *List) remove(e *Element) *Element {
e.prev.next = e.next
e.next.prev = e.prev
e.next = nil // avoid memory leaks
e.prev = nil // avoid memory leaks
e.list = nil
l.len--
return e
}
如果这是同步执行的,则不会有问题,但因为多个 go 例程正在其上运行。
假设我们有一个元素
E
,带有一个指向前一个和下一个的指针,以及两个作用于它的 goroutinesPREV - E - NEXT
GOROUTINE1 GOROUTINE2
READ - E.PREV returns element (E2) with `NEXT` -> E
REMOVE(E) is called
e.next = nil // avoid memory leaks
E2.NEXT.NEXT access occurs now Nil!!!
resulting in panic
关于go - 理解 Golang panic ,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/50040129/