golang中container/list包中的坑

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

golang中list包用法可以參看http://blog.csdn.net/chenbaoke/article/details/42780895

但是list包中大部分對於e *Element進行操作的元素都可能會導致程式崩潰,其根本原因是e是一個Element類型的指標,當然其也可能為nil,但是golang中list包中函數沒有對其進行是否為nil的檢查,變預設其非nil進行操作,所以這種情況下,便可能出現程式崩潰。

1.舉個簡單例子,Remove()函數

package mainimport ("container/list""fmt")func main() {l := list.New()l.PushBack(1)fmt.Println(l.Front().Value) //1value := l.Remove(l.Front())fmt.Println(value)            //1value1 := l.Remove(l.Front()) //panic: runtime error: invalid memory address or nil pointer dereferencefmt.Println(value1)}
從程式中可以直觀的看出程式崩潰,原因是list中只有1個元素,但是要刪除2個元素。但是再進一步查看一下原因,便會得出如下結果。

golang中Front()函數實現如下

func (l *List) Front() *Element {    if l.len == 0 {        return nil    }    return l.root.next}
由此可見,當第一次刪除之後。list的長度變為0,此時在調用l.Remove(l.Front()),其中l.Front()返回的是一個nil。


接下來再看golang中Remove()函數實現,該函數並沒有判定e是否為nil,變直接預設其為非nil,直接對其進行e.list或者e.Value取值操作。當e為nil時,這兩個操作都將會造成程式崩潰,這也就是為什麼上面程式會崩潰的原因。

func (l *List) Remove(e *Element) interface{} {if e.list == l {// if e.list == l, l must have been initialized when e was inserted// in l or l == nil (e is a zero Element) and l.remove will crashl.remove(e)}return e.Value}


2.(l *list)PushBackList(other *list)該函數用於將other list中元素添加在l list的後面。基本實現思想是取出other中所有元素,將其順次掛載在l列表中,但是golang中實現有問題,代碼如下。

func (l *List) PushBackList(other *List) {l.lazyInit()for i, e := other.Len(), other.Front(); i > 0; i, e = i-1, e.Next() {l.insertValue(e.Value, l.root.prev)}}
其具體思想是首先擷取other的長度n,然後迴圈n次取出其元素將其插入l中。問題就出現在迴圈n次,如果在這個過程中other的元素變化的話,例如其中有些元素被刪除了,這就導致e的指標可能為nil,此時再利用e.Value取值,程式便會崩潰。如下所示。

package mainimport ("container/list""runtime")func main() {runtime.GOMAXPROCS(8)l := list.New()ls := list.New()for i := 0; i < 10000; i++ {ls.PushBack(i)}go ls.Remove(l.Back())l.PushBackList(ls) //invalid memory address or nil pointer dereference}
如程式中所示,再講ls中元素添加到l過程中,如果ls中元素減少,程式便會崩潰。原因如上面分析。


建議:

在golang中如果對與list的操作只有串列操作,則只需要注意檢查元素指標是否為nil便可避免程式崩潰,如果程式中會並發處理list中元素,建議對list進行加寫鎖(全域鎖),然後再操作。注意,讀寫鎖無法保證平行處理list時程式的安全性。





著作權聲明:本文為博主原創文章,未經博主允許不得轉載。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.