亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

局部變量的返回地址生成意外值

局部變量的返回地址生成意外值

Go
繁星coding 2023-08-07 11:09:59
我寫了下面的代碼。我知道返回在函數中創建的變量的地址是錯誤的方法,因為創建的局部變量將位于堆棧中,并且在完成函數后該變量將從堆棧中彈出。我創建了一個名為“latif”的人。然后我使用了changeName()函數。它將 person 結構的名稱字段更改為“uluman”。它返回了局部變量的地址。函數完成后,局部變量應該被彈出。然后我調用了 sum() 函數來保證堆棧將發生變化(sum 函數的參數將被推送。換句話說,內存中的單元格值 x 點應該發生變化)。所以 x 指向堆棧中的某個位置。package main    import "fmt"    type Person struct{        name string        age int    }    func sum(a, b int)int{       return a+b    }    func (t Person ) changeName(value string)*Person{        t.name = value        return &t  //Delibiratly the address of the local variable is returned    }    func main(){        t := Person{name : "latif" }        fmt.Println("Before" , t.name)        x := t.changeName("uluman")        _= sum(5,10)        fmt.Println("After" , x.name)        return    }我預計fmt.Println(x.name)應該打印與“uluman”不同的內容,因為 x 指向堆棧地址并且它已經更改,但它打印了“uluman”。這里有什么問題嗎?
查看完整描述

1 回答

?
泛舟湖上清波郎朗

TA貢獻1818條經驗 獲得超3個贊

這被稱為“逃逸分析”。


Go編譯器嘗試找出變量的地址是否“轉義”了函數,如果是,它會在堆而不是堆棧中分配該變量。在這種情況下,它發現 的地址t逃逸了changeName函數,因此它被分配在堆中,而不是堆棧中。這就是你的程序有效的原因。


例如,這是構造結構的常見方法:


type X struct {

  ...

}


func NewX() *X {

   a:=X{}

   ...

   return &a

}

這里,a是在堆中分配的,而不是在堆棧上,因為編譯器知道它a會轉義函數。


以下內容也有效:


func f() {

  i:=0

  go func() {

    ...

    i++

    ...

   }()

}

上面,i轉義了f,因為地址i位于新創建的 goroutine 的閉包中。f回國后繼i續生活。


查看完整回答
反對 回復 2023-08-07
  • 1 回答
  • 0 關注
  • 162 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號