I'm using golangci-lint and I'm getting an error on the following code:
versions []ObjectDescription
... (populate versions) ...
for i, v := range versions {
res := createWorkerFor(&v)
...
}
the error is:
G601: Implicit memory aliasing in for loop. (gosec)
res := createWorkerFor(&v)
^
What does "implicit memory aliasing in for loop" mean, exactly? I could not find any error description in the golangci-lint documentation. I don't understand this error.
Indexing will solve the problem:
for i := range versions {
res := createWorkerFor(&versions[i])
...
}
The warning means, in short, that you are taking the address of a loop variable.
This happens because in for
statements the iteration variable(s) is reused. At each iteration, the value of the next element in the range expression is assigned to the iteration variable; v
doesn't change, only its value changes. Hence, the expression &v
is referring to the same location in memory.
The following code prints the same memory address four times:
for _, n := range []int{1, 2, 3, 4} {
fmt.Printf("%p\n", &n)
}
When you store the address of the iteration variable, or when you use it in a closure inside the loop, by the time you dereference the pointer, its value might have changed. Static analysis tools will detect this and emit the warning you see.
Common ways to prevent the issue are:
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)
}
In case you dereference sequentially within the loop and you know for sure that nothing is leaking the pointer, you might get away with ignoring this check. However the job of the linter is precisely to report code patterns that could cause issues, so it's a good idea to fix it anyway.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With