簡體   English   中英

這種類型的golang字符串切片可以在底層字節數組中泄漏內存嗎?

[英]Can this type of golang string slicing leak memory in underlying byte array?

buf = buf[n:]這樣的golang字符串切片會導致底層字節數組中的內存泄漏嗎?

如果是這樣,是否有可能獲得有關底層字節數組的任何信息(如容量或基本內存地址),以驗證泄漏?

請參閱以下示例代碼:

var buf string

func push(s string) {
    buf += s
    if len(buf) > 3 {
        buf = buf[len(buf)-3:] // can this line leak memory in underlying byte array?
    }
    fmt.Printf("buf=[%v]\n", buf)
}

在操場上跑吧

不,這個例子不會導致內存泄漏,因為每次調用push時都需要分配新的字符串。 有時可能會保留一些字節以減少分配,但是如何工作是一個不應該考慮的實現細節。

如果您正在考慮在分配切片操作的結果時可能出現的類似情況,但從不附加。 只要你理解切片的語義,每個說都沒有泄漏。

s := make([]byte, 1024)
s = s[1000:]
fmt.Println(s, len(s), cap(s))

此示例將保留分配的前1000個字節,但不可訪問。 答案很簡單,不要這樣做。 這並不難避免,如果確實需要確保已經發布了底層數組,請使用copy將字節移動到新的切片。

這與字符串相同:

s = s[1020:]
// may leave the first 1000 bytes allocated

這也很容易看出發生了什么,並避免。 如果你使用的是大字符串,那么你最好還是使用[]byte ,你可以更好地控制分配,並且可以在需要時復制字節。

將切片表達式應用於p := s[i:j]中的字符串的結果是一個字符串。 據我所知,Go語言規范( https://golang.org/ref/spec )沒有指定p將由與s相同的內存支持。

然而,在Go 1.6和早期版本中, p的實時引用將保留s不被垃圾收集。 然而,這可能會在Go的未來版本中發生變化。

一個有趣的事實是,Java String.substring方法在Java 8中以相同的方式實現。在Java 8中, substring返回一個副本。

回到你的例子。 每次調用push函數時,以下行實際上會創建一個新的字符串實例:

buf += s

舊的buf實例被垃圾收集。 所以你的例子不受上述問題的影響。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM