高頻golang面試題:簡單聊聊內存逃逸?

問題

知道golang的內存逃逸嗎?什麼狀況下會發生內存逃逸?golang

怎麼答

golang程序變量會攜帶有一組校驗數據,用來證實它的整個生命週期是否在運行時徹底可知。若是變量經過了這些校驗,它就能夠在棧上分配。不然就說它 逃逸 了,必須在堆上分配面試

能引發變量逃逸到堆上的典型狀況數組

  • 在方法內把局部變量指針返回 局部變量本來應該在棧中分配,在棧中回收。可是因爲返回時被外部引用,所以其生命週期大於棧,則溢出。
  • 發送指針或帶有指針的值到 channel 中。 在編譯時,是沒有辦法知道哪一個 goroutine 會在 channel 上接收數據。因此編譯器無法知道變量何時纔會被釋放。
  • 在一個切片上存儲指針或帶指針的值。 一個典型的例子就是 []*string 。這會致使切片的內容逃逸。儘管其後面的數組多是在棧上分配的,但其引用的值必定是在堆上。
  • slice 的背後數組被從新分配了,由於 append 時可能會超出其容量( cap )。 slice 初始化的地方在編譯時是能夠知道的,它最開始會在棧上分配。若是切片背後的存儲要基於運行時的數據進行擴充,就會在堆上分配。
  • 在 interface 類型上調用方法。 在 interface 類型上調用方法都是動態調度的 —— 方法的真正實現只能在運行時知道。想像一個 io.Reader 類型的變量 r , 調用 r.Read(b) 會使得 r 的值和切片b 的背後存儲都逃逸掉,因此會在堆上分配。

舉例

  • 經過一個例子加深理解,接下來嘗試下怎麼經過 go build -gcflags=-m 查看逃逸的狀況。
package main
import "fmt" type A struct {  s string } // 這是上面提到的 "在方法內把局部變量指針返回" 的狀況 func foo(s string) *A {  a := new(A)  a.s = s  return a //返回局部變量a,在C語言中妥妥野指針,但在go則ok,但a會逃逸到堆 } func main() {  a := foo("hello")  b := a.s + " world"  c := b + "!"  fmt.Println(c) } 複製代碼

執行go build -gcflags=-m main.gomarkdown

go build -gcflags=-m main.go
# command-line-arguments ./main.go:7:6: can inline foo ./main.go:13:10: inlining call to foo ./main.go:16:13: inlining call to fmt.Println /var/folders/45/qx9lfw2s2zzgvhzg3mtzkwzc0000gn/T/go-build409982591/b001/_gomod_.go:6:6: can inline init.0 ./main.go:7:10: leaking param: s ./main.go:8:10: new(A) escapes to heap ./main.go:16:13: io.Writer(os.Stdout) escapes to heap ./main.go:16:13: c escapes to heap ./main.go:15:9: b + "!" escapes to heap ./main.go:13:10: main new(A) does not escape ./main.go:14:11: main a.s + " world" does not escape ./main.go:16:13: main []interface {} literal does not escape <autogenerated>:1: os.(*File).close .this does not escape 複製代碼
  • ./main.go:8:10: new(A) escapes to heap 說明 new(A) 逃逸了,符合上述提到的常見狀況中的第一種。app

  • ./main.go:14:11: main a.s + " world" does not escape 說明 b 變量沒有逃逸,由於它只在方法內存在,會在方法結束時被回收。oop

  • ./main.go:15:9: b + "!" escapes to heap 說明 c 變量逃逸,經過fmt.Println(a ...interface{})打印的變量,都會發生逃逸,感興趣的朋友能夠去查查爲何。學習

  • 以上操做其實就叫逃逸分析下篇文章,跟你們聊聊怎麼用一個比較trick的方法使變量不逃逸。方便你們在面試官面前秀一波ui

文章推薦:

若是你想天天學習一個知識點?

相關文章
相關標籤/搜索