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

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

for循環中的隱式內存別名

for循環中的隱式內存別名

Go
呼如林 2022-06-13 10:58:22
我正在使用 golangci-lint,但在以下代碼中出現錯誤:versions []ObjectDescription... (populate versions) ...for i, v := range versions {    res := createWorkerFor(&v)    ...}錯誤是:G601: Implicit memory aliasing in for loop. (gosec)                     res := createWorkerFor(&v)                                            ^“for循環中的隱式內存別名”到底是什么意思?我在 golangci-lint 文檔中找不到任何錯誤描述。我不明白這個錯誤。
查看完整描述

2 回答

?
德瑪西亞99

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

簡而言之,警告意味著您正在獲取循環變量的地址。


發生這種情況是因為在for語句中重復使用了迭代變量。在每次迭代中,將范圍表達式中下一個元素的值賦給迭代變量;v不會改變,只會改變它的值。因此,該表達式&v指的是內存中的同一位置。


以下代碼四次打印相同的內存地址:


for _, n := range []int{1, 2, 3, 4} {

    fmt.Printf("%p\n", &n)

}

當您存儲迭代變量的地址時,或者當您在循環內的閉包中使用它時,當您取消引用指針時,它的值可能已經改變。靜態分析工具會檢測到這一點并發出您看到的警告。


防止該問題的常見方法是:


索引范圍切片/數組/映射。這將獲取第 i 個位置的實際元素的地址,而不是迭代變量

for i := range versions {

    res := createWorkerFor(&versions[i])

}

重新分配循環內的迭代變量

for _, v := range versions {

    v := v

    res := createWorkerFor(&v) // this is now the address of the inner v

}

使用閉包,將迭代變量作為參數傳遞給閉包

for _, v := range versions { 

    go func(arg ObjectDescription) {

        x := &arg // safe

    }(v)

}

如果您在循環中按順序取消引用并且您確定沒有任何內容泄漏指針,您可能會忽略此檢查而僥幸逃脫。然而,linter 的工作正是報告可能導致問題的代碼模式,因此無論如何修復它都是一個好主意。


查看完整回答
反對 回復 2022-06-13
?
江戶川亂折騰

TA貢獻1851條經驗 獲得超5個贊

索引將解決問題:


for i := range versions {

    res := createWorkerFor(&versions[i])

    ...


}


查看完整回答
反對 回復 2022-06-13
  • 2 回答
  • 0 關注
  • 564 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

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

幫助反饋 APP下載

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

公眾號

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