首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >隐式内存混叠for循环

隐式内存混叠for循环
EN

Stack Overflow用户
提问于 2020-06-18 08:55:02
回答 2查看 18.7K关注 0票数 42

我使用的是golangci-lint,下面的代码出错了:

代码语言:javascript
运行
复制
versions []ObjectDescription
... (populate versions) ...

for i, v := range versions {
    res := createWorkerFor(&v)
    ...

}

错误是:

代码语言:javascript
运行
复制
G601: Implicit memory aliasing in for loop. (gosec)
                     res := createWorkerFor(&v)
                                            ^

“内隐内存混叠for循环”到底是什么意思?我找不到任何错误的描述,在戈兰奇衣领的文档。我不明白这个错误。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-06-20 13:47:44

索引将解决这个问题:

代码语言:javascript
运行
复制
for i := range versions {
    res := createWorkerFor(&versions[i])
    ...

}
票数 41
EN

Stack Overflow用户

发布于 2021-07-04 18:45:27

简而言之,这个警告意味着您正在接受一个循环变量的地址。

这是因为在for statements中迭代变量被重用。在每次迭代时,范围表达式中的下一个元素的值被分配给迭代变量;v不会改变,只会改变它的值。因此,表达式&v指的是内存中相同的位置。

以下代码四次打印相同的内存地址:

代码语言:javascript
运行
复制
for _, n := range []int{1, 2, 3, 4} {
    fmt.Printf("%p\n", &n)
}

当您存储迭代变量的地址,或者在循环内部的闭包中使用它时,当您取消引用指针时,它的值可能已经发生了变化。静态分析工具将检测到这一点,并发出您看到的警告。

防止这一问题的共同办法是:

  • 索引远程切片/数组/地图。这将在第一位置获取实际元素的地址,而不是迭代变量

代码语言:javascript
运行
复制
for i := range versions {
    res := createWorkerFor(&versions[i])
}

  • 重新分配循环

中的迭代变量

代码语言:javascript
运行
复制
for _, v := range versions {
    v := v
    res := createWorkerFor(&v) // this is now the address of the inner v
}

使用闭包的

  • ,将迭代变量作为参数传递给闭包

代码语言:javascript
运行
复制
for _, v := range versions { 
    go func(arg ObjectDescription) {
        x := &arg // safe
    }(v)
}

如果您在循环中按顺序取消引用,并且确信没有泄漏指针,您可能会忽略此检查。然而,linter的工作恰恰是报告可能导致问题的代码模式,所以无论如何修复它是个好主意。

票数 55
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62446118

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档