为了账号安全,请及时绑定邮箱和手机立即绑定

这种类型的 golang 字符串切片会在底层字节数组中泄漏内存吗?

这种类型的 golang 字符串切片会在底层字节数组中泄漏内存吗?

Go
精慕HU 2021-12-06 14:56:11
golang 字符串切片是否buf = buf[n:]会导致底层字节数组中的内存泄漏?如果是这样,是否可以获取有关底层字节数组的任何信息(如容量或基本内存地址)以验证泄漏?请参阅下面的示例代码:var buf stringfunc 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)}
查看完整描述

2 回答

?
天涯尽头无女友

TA贡献1831条经验 获得超9个赞

不,这个例子不会导致内存泄漏,因为每次调用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任何方式,这样您可以更好地控制分配,并且可以在需要时复制字节。


查看完整回答
反对 回复 2021-12-06
?
临摹微笑

TA贡献1982条经验 获得超2个赞

将切片表达式应用于字符串中的结果p := s[i:j]是一个字符串。据我所知,Go 语言规范(https://golang.org/ref/spec)没有指定p将由与s.

然而,在 Go 1.6 和更早版本中,一个实时引用ps不会被垃圾收集。然而,这可能会在 Go 的未来版本中改变。

一个有趣的事实是,Java 中的String.substring方法在 Java 8 之前以相同的方式实现。然而,在 Java 8 中substring返回一个副本。

回到你的例子。每次调用push函数时,以下行实际上都会创建一个新的字符串实例:

buf += s

buf 的旧实例被垃圾收集。所以你的例子不受上述问题的影响。


查看完整回答
反对 回复 2021-12-06
  • 2 回答
  • 0 关注
  • 327 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信