了解Golang恐慌

时间:2018-04-26 10:01:01

标签: go

我有一些非常间歇性的Golang代码(每隔几个小时一次),导致恐慌,我需要一些指导,了解如何找到原因。代码是这个(带行号):

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()时发生混乱。发送到此频道的代码为:

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: 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

恐慌告诉我哪个是错误的?没有关于分配的抱怨并且首先发送到频道,所以我不明白这是怎么回事。 newDatagramList显然已初始化(并且频道已运行并接收消息一段时间)。

我如何确定是什么让我砰的一声?

1 个答案:

答案 0 :(得分:2)

恐慌堆:

java.lang.ClassCastException: cannot assign instance of java.lang.invoke.SerializedLambda to field org.opencell.spark.jobs.UsageJobDS.rateEDRs of type org.apache.spark.api.java.function.CoGroupFunction in instance of org.opencell.spark.jobs.UsageJobDS
    at java.io.ObjectStreamClass$FieldReflector.setObjFieldValues(ObjectStreamClass.java:2233)
    at java.io.ObjectStreamClass.setObjFieldValues(ObjectStreamClass.java:1405)
    at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2288)

在顶部列出的框架中发出“无效的内存地址或无指针取消引用”

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)

看起来是from godoc

 /usr/lib/go-1.6/src/container/list/list.go:139 +0x1c1

这很酷,因为它在这个框架中看起来在// 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有许多不同的操作:

remove

如果这是同步执行的,那么就不会出现问题,但因为有多个go例程正在运行。

假设我们有一个元素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 } ,带有指向前一个和下一个的指针,以及两个作用于它的goroutines

E