dougai8673 2018-04-26 10:01 采纳率: 100%
浏览 75
已采纳

了解Golang恐慌

I have some Golang code that is, very intermittently (once every few hours), resulting in a panic and I need some guidance understanding how to find the cause. The code is this (with line numbers):

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 }

...and the panic occurs when newDatagramList.PushBack() is called at line 420. The code sending into this channel is:

audio-in.go:

    thing := new(MyThing)
    ...
    MyChannel <- thing

...and, to complete the picture, there is a separate timed go func() which processes newDatagramList as follows:

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)
        }
}

The panic output is:

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

Which thing is the panic telling me is at fault here? There was no complaint about the allocation and send into the channel in the first place, so I don't see how that can be wrong. newDatagramList is clearly initialised (and the channel has been running and receiving messages for some time).

How do I go about determining what's making me go bang?

  • 写回答

1条回答 默认 最新

  • dongxin8392 2018-04-26 14:05
    关注

    The panic stack:

    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
    

    Is saying that an "invalid memory address or nil pointer dereference" is occurring at the top listed frame

     container/list.(*List).PushBack(0xc820054e40, 0x6c4f80, 0xc827294e20, 0xc8273e0b01)
    

    On

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

    Which looks to be 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)
    }
    

    This is cool since it's in this frame it looks to be erroring on l.root.prev

    The datatype that is being built on container/list is completely unsynchronized and there are many interleaving of go routines that could result in an in-between state where list element pointers are being added removed at the same time.

    For example remove has many different operations:

    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
    }
    

    If this was executed synchronously there wouldn't be an issue but because multiple go routines are operating on it.

    Suppose we have an element E, with a pointer to a previous and a next, and two goroutines acting on it

    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 
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 对于相关问题的求解与代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 信号傅里叶变换在matlab上遇到的小问题请求帮助
  • ¥15 保护模式-系统加载-段寄存器
  • ¥15 电脑桌面设定一个区域禁止鼠标操作
  • ¥15 求NPF226060磁芯的详细资料
  • ¥15 使用R语言marginaleffects包进行边际效应图绘制
  • ¥20 usb设备兼容性问题
  • ¥15 错误(10048): “调用exui内部功能”库命令的参数“参数4”不能接受空数据。怎么解决啊
  • ¥15 安装svn网络有问题怎么办