Golang的内存泄漏场景.pdfVIP

  1. 1、本文档共4页,可阅读全部内容。
  2. 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
  3. 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  4. 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
  5. 5、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
  6. 6、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们
  7. 7、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
  8. 8、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
Golang的内存泄漏场景 看到个好⽂章,翻译⼀遍分享⼀下。 内存泄漏场景 当使⽤⽀持⾃动垃圾回收的语⾔进⾏编程时,通常我们不需要关⼼内存泄漏问题,因为运⾏时会定期⼿机⽆⽤的内存。但是我们确实需要了 解⼀些特殊场景,这些场景可能导致似(kind-of)/真内存泄漏。⽂章的后⾯部分会列出⼀些这样的场景。 ⼦字符串导致的似内存泄漏 Go语⾔规范没有指明⼀个⼦字符串表达式中的基字符串和结果字符串是否应该共⽤同个底层内存块来管理两个字符串的底层字节序列。标 准的Go编译器/运⾏时确实是让他们共享了同个底层内存块。这是⼀个很好的设计,不管是从内存还是CPU消化⾓度。但是有时它可能会导 致某种内存泄漏。 ⽐如,在下例中的 demo 函数被调⽤后,会有⼤约 1M字节的似内存,知道package级变量s0在其他地⽅被修改。 ⼀个 级变量 var s0 string // package ⼀个⽤作⽰例的函数 // func f(s1 string) { s0 = s1[:50] 现在, 与 共享了同个底层内存块。尽管 现在不存活了, // s0 s1 s1 仍然存活。所以尽管只⽤到了 个字节,其他字节访问不到, // s0 50 他们共享的内存块并不会被回收。 // } func demo() { 字节 s := createStringWithLengthOnHeap(1 20) // 1M f(s) } 为了避免这种似内存泄漏,我们可以转换底层字符串为⼀个[]byte ,然后把 []byte 转换回 string . func f(s1 string) { s0 = string([]byte(s1[:50])) } 上⾯这种避免这似内存泄漏的⽅法的缺点是,在会话处理过程中,会有两个50字节的副本,其中之⼀是没必要的。 我们可以利⽤标准Go编译器的其中⼀个优化来避免⾮必要的副本,只需要浪费⼀个字节的内存。 func f(s1 string) { s0 = ( + s1[:50])[1:] } 以上⽅法的缺点是,这个编译器优化在以后可能会被取消,并且这个优化可能在其他编译器中没有实现。 第三种避免这个似内存泄漏的⽅法是使⽤strings.Builder ,从Go 1.10开始有的。 import strings func f(s1 string) { var b strings.Builder b .Grow(50) b .WriteString(s1[:50]) s0 = b .String() } 第三种⽅式的缺点是相⽐前两种有些⿇烦。⼀个好消息是,从Go 1.12起,我们可以调⽤strings 标准包的 Repeat 函数,传递 count 参数 为 1 来克隆⼀个字符串。从Go 1.12起,string.Repeat 的底层实现会使⽤ strings.Builder 来避免不必要的复制。 从Go 1.17起, strings 标准包⾥加⼊了⼀个 Clone 函数。它成了做这个事的最好⽅法。 由⼦切⽚导致的似内存泄漏 与⼦字符串类似,⼦切⽚也可能导致似内存泄漏。在以下代码中,在g 函数被调⽤后,占据 s1 ⼤部分内存块的⼤量元素将会丢失(如果没有 更多值指向这个内存块)。 var s0 []int func g(s1 []int) { 假设 的长度远⼤于 // s1 30 s0 = s1[len(s1)-30:] } 如果我们想要避免这个似内存泄漏,我们必须为s0 复制30个元素,这样 s0 的存活就不会阻⽌ s1 的内存块被回收了。 func g(s1 []int) { s0 = make([]int, 30) copy(s0, s1[len(s1)-30:]) 现在,如果没有其他值引⽤着存着 的元素的内存块, // s1 它就可以被回收了。 // } 没有重置丢失的切⽚元素的指针导致的似内存泄漏 在以下代码中,在 h 函数被调⽤后,为 s 的第⼀个和最后⼀个元素分配的内存块将会丢失。 func

文档评论(0)

A19855058659 + 关注
实名认证
文档贡献者

该用户很懒,什么也没介绍

1亿VIP精品文档

相关文档