Go version
go version go1.22.1 windows/amd64
Output of go env
in your module/workspace:
set GO111MODULE=
set GOARCH=amd64
set GOBIN=
set GOCACHE=C:\Users\AppData\Local\go-build
set GOENV=C:\Users\AppData\Roaming\go\env
set GOEXE=.exe
set GOEXPERIMENT=
set GOFLAGS=
set GOHOSTARCH=amd64
set GOHOSTOS=windows
set GOINSECURE=
set GOMODCACHE=C:\Users\go\pkg\mod
set GONOPROXY=git.mycompany.com,github.com/my/private
set GONOSUMDB=git.mycompany.com,github.com/my/private
set GOOS=windows
set GOPATH=C:\Users\go
set GOPRIVATE=git.mycompany.com,github.com/my/private
set GOPROXY=https://goproxy.io,direct
set GOROOT=F:\env\Go
set GOSUMDB=sum.golang.org
set GOTMPDIR=
set GOTOOLCHAIN=auto
set GOTOOLDIR=F:\env\Go\pkg\tool\windows_amd64
set GOVCS=
set GOVERSION=go1.22.1
set GCCGO=gccgo
set GOAMD64=v1
set AR=ar
set CC=gcc
set CXX=g++
set CGO_ENABLED=1
set GOMOD=F:\work\go.mod
set GOWORK=
set CGO_CFLAGS=-O2 -g
set CGO_CPPFLAGS=
set CGO_CXXFLAGS=-O2 -g
set CGO_FFLAGS=-O2 -g
set CGO_LDFLAGS=-O2 -g
set PKG_CONFIG=pkg-config
set GOGCCFLAGS=-m64 -mthreads -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=C:\Users\AppData\Local\Temp\go-build1951953803=/tmp/go-build -gno-record-gcc-switches
What did you do?
I want to use slice to store some data, which will use for some calculations. There are two slices have the same pointer, but the data and behavior are unpredictable when I append data to them.
What did you see happen?
code: fmt.Printf("地址(%p),值:%v \n", xz.dAA, xz.dAA) txz := yXA[32] fmt.Printf("地址(%p),值:%v \n", txz.dAA, txz.dAA)
txz.dAA = append(txz.dAA, [][3]int{{1023, 68, 69}})
fmt.Printf("地址(%p),值:%v \n", xz.dAA, xz.dAA)
txz := yXA[32]
fmt.Printf("地址(%p),值:%v \n", txz.dAA, txz.dAA)
output: 地址(0xc00efc9e00),值:[[[1012 36 44] [1012 50 68]] [[1013 34 71]] [[1014 32 72]] [[1015 30 73]] [[1016 22 73]] [[1017 18 74]] [[1018 14 74]] [[1019 12 74]] [[1020 34 75]] [[1021 34 75]] [[1022 32 75]]]
地址(0xc00efc9e00),值:[[[1012 36 44] [1012 50 68]] [[1013 34 71]] [[1014 32 72]] [[1015 30 73]] [[1016 22 73]] [[1017 18 74]] [[1018 14 74]] [[1019 12 74]] [[1020 34 75]] [[1021 34 75]] [[1022 32 75]] [[1023 31 47]]]
地址(0xc00efc9e00),值:[[[1012 36 44] [1012 50 68]] [[1013 34 71]] [[1014 32 72]] [[1015 30 73]] [[1016 22 73]] [[1017 18 74]] [[1018 14 74]] [[1019 12 74]] [[1020 34 75]] [[1021 34 75]] [[1022 32 75]] [[1023 68 69]]]
地址(0xc00efc9e00),值:[[[1012 36 44] [1012 50 68]] [[1013 34 71]] [[1014 32 72]] [[1015 30 73]] [[1016 22 73]] [[1017 18 74]] [[1018 14 74]] [[1019 12 74]] [[1020 34 75]] [[1021 34 75]] [[1022 32 75]] [[1023 68 69]]]
What did you expect to see?
If the slices have same pointer, then they must have same data.
Comment From: gabyhelp
Similar Issues
- Unexpected different behavior with append on a byte slice vs int slice. #45436
- Some inconsistent Values on Slice output #34428
- bug: look like to watch same address when assign to another variable from sub-slice. #56617
- Convert slice of type A to slice of pointers to type A #22791
- It is a GC issue? #44317
(Emoji vote if this was helpful or unhelpful; more detailed feedback welcome in this discussion.)
Comment From: seankhliao
Unlike many projects, the Go project does not use GitHub Issues for general discussion or asking questions. GitHub Issues are used for tracking bugs and proposals only.
For questions please refer to https://github.com/golang/go/wiki/Questions
Comment From: xice-blue
Unlike many projects, the Go project does not use GitHub Issues for general discussion or asking questions. GitHub Issues are used for tracking bugs and proposals only.
For questions please refer to https://github.com/golang/go/wiki/Questions
This is a bug. This is not a concurrency issue. It was happened on a debug model, and I did not use any concurrency logic.
Comment From: xice-blue
There is a big loop (tens millions of times) out of the code, and there are tens thousands slices were created and disdroyed. Before about 3 millions of times of the loop, the slice has correct behavior. But the bug must happen before the end of the loop.
Comment From: seankhliao
please provide a self contained reproducer for the issue.
Comment From: xice-blue
In the test code, it is worse when the 'n' becomes smaller. Please see the line of fmt.printf(...)
.
package test
import (
"fmt"
"math/rand"
"testing"
)
type txs struct {
r int
dAA [][][3]int
}
func (zg *txs) j(i, j int) {
ldA := zg.dAA[len(zg.dAA)-1]
if i > ldA[0][0] {
zg.dAA = append(zg.dAA, [][3]int{{i, j, j}})
} else {
ldA[len(ldA)-1][2] = j
}
}
func (zg *txs) l(ng *txs) {
ic := zg.dAA[0][0][0] - ng.dAA[0][0][0]
if ic < 0 {
for ngi := range ng.dAA {
zgi := ngi - ic
zgx := zg.dAA[zgi][0][1]
ngx := ng.dAA[ngi][0][1]
if zgx < ngx {
zg.dAA[zgi] = append(zg.dAA[zgi], ng.dAA[ngi]...)
} else if ngx < zgx {
zg.dAA[zgi] = append(ng.dAA[ngi], zg.dAA[zgi]...)
}
}
} else {
for ngi := ic; ngi < len(ng.dAA); ngi++ {
zgi := ngi - ic
zgdA := zg.dAA[zgi]
zgzx := zgdA[0][1]
zgyx := zgdA[len(zgdA)-1][2]
ngdA := ng.dAA[ngi]
ngzx := ngdA[0][1]
ngyx := ngdA[len(ngdA)-1][2]
if zgyx < ngzx {
zg.dAA[zgi] = append(zgdA, ngdA...)
} else if zgzx > ngyx {
zg.dAA[zgi] = append(ngdA, zgdA...)
}
}
if ic > 0 {
zg.dAA = append(ng.dAA[:ic], zg.dAA...)
}
}
ng.dAA = zg.dAA
}
func TestSliceBug(t *testing.T) {
n := 3
cn := 0
syXA := make([]*txs, 2000)
yXA := make([]*txs, 2000)
zx := rand.Int() % n
xz := &txs{zx, [][][3]int{{{0, 0, 0}}}}
syXA[0] = xz
for j := range 2000 {
x := rand.Int() % n
if zx == x {
xz.j(0, j)
} else {
xz = &txs{zx, [][][3]int{{{0, j, j}}}}
zx = x
}
syXA[j] = xz
}
for i := 1; i < 3000; i++ {
zx = rand.Int() % n
sxz := syXA[0]
if zx == sxz.r {
xz = sxz
xz.j(i, 0)
} else {
xz = &txs{zx, [][][3]int{{{i, 0, 0}}}}
}
yXA[0] = xz
for j := 1; j < 2000; j++ {
x := rand.Int() % n
sxz := syXA[j]
if x == sxz.r {
if xz == sxz {
xzdl := len(xz.dAA)
txz := syXA[xz.dAA[xzdl-1][0][1]]
txzdl := len(txz.dAA)
xzdap := fmt.Sprintf("%p", xz.dAA)
txzdap := fmt.Sprintf("%p", txz.dAA)
se := false
if xzdap == txzdap {
if xzdl == txzdl {
cn++
} else {
se = true
fmt.Printf("Correct times: %v \n", cn)
fmt.Printf("Error! Pointer(%p), values:%v \n", xz.dAA, xz.dAA)
fmt.Printf("Error! Pointer(%p), values:%v \n", txz.dAA, txz.dAA)
}
}
xz.j(i, j)
if se {
fmt.Printf("Error! Pointer(%p), values:%v \n", xz.dAA, xz.dAA)
fmt.Printf("Error! Pointer(%p), values:%v \n", txz.dAA, txz.dAA)
t.FailNow()
}
} else if x == xz.r {
xzdl := len(xz.dAA)
txz := syXA[xz.dAA[xzdl-1][0][1]]
txzdl := len(txz.dAA)
xzdap := fmt.Sprintf("%p", xz.dAA)
txzdap := fmt.Sprintf("%p", txz.dAA)
se := false
if xzdap == txzdap {
if xzdl == txzdl {
cn++
} else {
se = true
fmt.Printf("Correct times: %v \n", cn)
fmt.Printf("Error! Pointer(%p), values:%v \n", xz.dAA, xz.dAA)
fmt.Printf("Error! Pointer(%p), values:%v \n", txz.dAA, txz.dAA)
}
}
xz.j(i, j)
if se {
fmt.Printf("Error! Pointer(%p), values:%v \n", xz.dAA, xz.dAA)
fmt.Printf("Error! Pointer(%p), values:%v \n", txz.dAA, txz.dAA)
t.FailNow()
}
xz.l(sxz)
} else {
xz = sxz
zx = x
xzdl := len(xz.dAA)
txz := syXA[xz.dAA[xzdl-1][0][1]]
txzdl := len(txz.dAA)
xzdap := fmt.Sprintf("%p", xz.dAA)
txzdap := fmt.Sprintf("%p", txz.dAA)
se := false
if xzdap == txzdap {
if xzdl == txzdl {
cn++
} else {
se = true
fmt.Printf("Correct times: %v \n", cn)
fmt.Printf("Error! Pointer(%p), values:%v \n", xz.dAA, xz.dAA)
fmt.Printf("Error! Pointer(%p), values:%v \n", txz.dAA, txz.dAA)
}
}
xz.j(i, j)
if se {
fmt.Printf("Error! Pointer(%p), values:%v \n", xz.dAA, xz.dAA)
fmt.Printf("Error! Pointer(%p), values:%v \n", txz.dAA, txz.dAA)
t.FailNow()
}
}
} else if x == zx {
xzdl := len(xz.dAA)
txz := syXA[xz.dAA[xzdl-1][0][1]]
txzdl := len(txz.dAA)
xzdap := fmt.Sprintf("%p", xz.dAA)
txzdap := fmt.Sprintf("%p", txz.dAA)
se := false
if xzdap == txzdap {
if xzdl == txzdl {
cn++
} else {
se = true
fmt.Printf("Correct times: %v \n", cn)
fmt.Printf("Error! Pointer(%p), values:%v \n", xz.dAA, xz.dAA)
fmt.Printf("Error! Pointer(%p), values:%v \n", txz.dAA, txz.dAA)
}
}
xz.j(i, j)
if se {
fmt.Printf("Error! Pointer(%p), values:%v \n", xz.dAA, xz.dAA)
fmt.Printf("Error! Pointer(%p), values:%v \n", txz.dAA, txz.dAA)
t.FailNow()
}
} else {
zx = x
xz = &txs{zx, [][][3]int{{{i, j, j}}}}
}
yXA[j] = xz
}
tt := syXA
syXA = yXA
yXA = tt
}
}
Comment From: randall77
I'm afraid from your test program it isn't obvious that there is any bug. It would help if the program could be minimized.
If the slices have same pointer, then they must have same data.
That's not true. Slices can have the same pointer but different lengths, which is what appears to be happening in your error prints.
package main
import "fmt"
func main() {
a := []int{3, 4}
b := a[:1]
fmt.Printf("%p %p %v %v\n", a, b, a, b)
}
0x14000110020 0x14000110020 [3 4] [3]
Comment From: xice-blue
I'm afraid from your test program it isn't obvious that there is any bug. It would help if the program could be minimized.
If the slices have same pointer, then they must have same data.
That's not true. Slices can have the same pointer but different lengths, which is what appears to be happening in your error prints.
``` package main
import "fmt"
func main() { a := []int{3, 4} b := a[:1] fmt.Printf("%p %p %v %v\n", a, b, a, b) } ```
0x14000110020 0x14000110020 [3 4] [3]
There is only one place of using a[:]
model, zg.dAA = append(ng.dAA[:ic], zg.dAA...)
, and then the slice was set to two txses, and the lenth of the backend array should be same with the slice. The propose of "func l" is to merge two slices. So that I confused why that happened when the lenth of slice should be same as the lenth of the backend array (but I cannot see the backend array).
Comment From: randall77
There is only one place of using a[:] model
The same behavior can happen using append
instead of slicing.
package main
import "fmt"
func main() {
a := []int{3, 4}
b := append(a, 5)
c := append(b, 6)
fmt.Printf("%p %p %v %v\n", b, c, b, c)
}
0x14000126000 0x14000126000 [3 4 5] [3 4 5 6]
Comment From: xice-blue
There is only one place of using a[:] model
The same behavior can happen using
append
instead of slicing.``` package main
import "fmt"
func main() { a := []int{3, 4} b := append(a, 5) c := append(b, 6) fmt.Printf("%p %p %v %v\n", b, c, b, c) } ```
0x14000126000 0x14000126000 [3 4 5] [3 4 5 6]
For your statement, a and b are [:] model, and a is smaller. When append to b, a will not change.
func TestSlices(t *testing.T) {
a := []int{1, 2, 3, 4, 5}
b := a[:3]
c := append(a[:4], 6)
fmt.Printf("%v,%v", b, c)
}
[1 2 3],[1 2 3 4 6]PASS
This is also a different behavior with the bug code.
Comment From: randall77
I'm still not understanding what you think the bug is.
Comment From: xice-blue
I'm still not understanding what you think the bug is.
Whatever the behavior of slice shoud be, it must be keep the same in anywhere (except for concurrency case). If slices are [:] model, and the lenth of them are different, then append to one should not change another, right? If slices are full model of the backend array, they should have same value,right? But, in the bug code, sometimes, the slices have same value, sometimes, the slices have different lenth, but after append to one, another is changed. I cannot see the code of append, so that I don't know why the behaviors of slice in the bug code will happen.
Comment From: randall77
Whatever the behavior of slice shoud be, it must be keep the same in anywhere (except for concurrency case).
I think you are misunderstanding slices. Several slices can refer to the same underlying array. Modifications through one slice, including through the use of append
, can be seen through the other slices.
Think of slices as pointers.
If slices are [:] model, and the lenth of them are different, then append to one should not change another, right?
Wrong.
package main
import "fmt"
func main() {
a := []int{3, 4}
b := append(a, 5)
c := append(b, 6)
fmt.Printf("%v\n", c)
d := append(b, 7)
fmt.Printf("%v %v\n", c, d)
}
[3 4 5 6]
[3 4 5 7] [3 4 5 7]
You probably want to read https://go.dev/blog/slices-intro.
Comment From: xice-blue
Whatever the behavior of slice shoud be, it must be keep the same in anywhere (except for concurrency case).
I think you are misunderstanding slices. Several slices can refer to the same underlying array. Modifications through one slice, including through the use of
append
, can be seen through the other slices.Think of slices as pointers.
If slices are [:] model, and the lenth of them are different, then append to one should not change another, right?
Wrong.
``` package main
import "fmt"
func main() { a := []int{3, 4} b := append(a, 5) c := append(b, 6) fmt.Printf("%v\n", c) d := append(b, 7) fmt.Printf("%v %v\n", c, d) } ```
[3 4 5 6] [3 4 5 7] [3 4 5 7]
You probably want to read https://go.dev/blog/slices-intro.
I understood this sub slice case. But my case is not the sub slice case. I only need the 'c', so that I set the 'c' to everywhere. But the behavior of append c
is different in the bug code.
Comment From: randall77
But my case is not the sub slice case. I only need the 'c', so that I set the 'c' to everywhere.
Normally the way to ensure that you never use the old slice is to always overwrite the slice you're appending to. Your code does that in some cases, like
zg.dAA[zgi] = append(zg.dAA[zgi], ng.dAA[ngi]...)
But in other cases it isn't.
zg.dAA[zgi] = append(ng.dAA[ngi], zg.dAA[zgi]...)
How do you know that later on you're not appending something else to ng.dAA[ngi]
?
In any case, we're going to need a more demonstrable bug reproducer to reopen this issue. Just saying "it isn't doing what I expect" could be a bug in Go or a bug in your expectations. It's hard to tell because the expected behavior of the program you posted is inscrutable.
Comment From: xice-blue
But my case is not the sub slice case. I only need the 'c', so that I set the 'c' to everywhere.
Normally the way to ensure that you never use the old slice is to always overwrite the slice you're appending to. Your code does that in some cases, like
zg.dAA[zgi] = append(zg.dAA[zgi], ng.dAA[ngi]...)
But in other cases it isn't.
zg.dAA[zgi] = append(ng.dAA[ngi], zg.dAA[zgi]...)
How do you know that later on you're not appending something else to
ng.dAA[ngi]
?In any case, we're going to need a more demonstrable bug reproducer to reopen this issue. Just saying "it isn't doing what I expect" could be a bug in Go or a bug in your expectations. It's hard to tell because the expected behavior of the program you posted is inscrutable.
This is second level of slice, but the bug is for first level of slice. I have no question for one level slice, and the second level of slice has no issue.
The logic is complex, and I hope you can track the append code which I cannot track. Append code is black box for me......