Стек паники:
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
Говорит, что "неверный адрес памяти или разыменование нулевого указателя" происходит в верхнем списке кадров
container/list.(*List).PushBack(0xc820054e40, 0x6c4f80, 0xc827294e20, 0xc8273e0b01)
Вкл.
/usr/lib/go-1.6/src/container/list/list.go:139 +0x1c1
Что выглядит как от 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
, с указателем на предыдущий и следующий, и две goroutines, действующие на него
PREV - 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