golang / go

The Go programming language
https://go.dev
BSD 3-Clause "New" or "Revised" License
124.04k stars 17.67k forks source link

affected/package: a bug when appending an item to a 2d slice #51426

Closed wangfengfly closed 2 years ago

wangfengfly commented 2 years ago

What version of Go are you using (go version)?

$ go version
go version go1.16.7 darwin/amd64

Does this issue reproduce with the latest release?

Not sure

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
GO111MODULE="auto"
GOARCH="amd64"
GOBIN=""
GOCACHE="/Users/wangfeng14/Library/Caches/go-build"
GOENV="/Users/wangfeng14/Library/Application Support/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOMODCACHE="/Users/wangfeng14/go/pkg/mod"
GOOS="darwin"
GOPATH="/Users/wangfeng14/go"
GOPROXY="https://goproxy.cn,direct"
GOROOT="/usr/local/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/darwin_amd64"
GOVCS=""
GOVERSION="go1.16.7"
GCCGO="gccgo"
AR="ar"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
GOMOD=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -arch x86_64 -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/_l/7g74_14j58gc74zwxpwl9mr80000gn/T/go-build3920822002=/tmp/go-build -gno-record-gcc-switches -fno-common"

What did you do?

Given an integer array nums of unique elements, return all possible subsets (the power set). The leetcode problem link: https://leetcode.com/problems/subsets/

package main

import "fmt"

func recursion(nums []int, n int) [][]int {
    if n == 0 {
        res := [][]int{}
        res = append(res, []int{})
        return res
    }

    subsets := recursion(nums, n-1)
    new := [][]int{}
    for i := 0; i < len(subsets); i++ {
        /*if n == 5 && i == 7 {
            fmt.Print(subsets[15], subsets[i], nums[n-1])
        }*/
        new = append(new, append(subsets[i], nums[n-1]))
        /*if n == 5 && i == 7 {
            fmt.Println(subsets[15], subsets[i], new[len(new)-1])
        }*/
    }
    return append(subsets, new...)
}

func subsets(nums []int) [][]int {
    if len(nums) == 0 {
        return nil
    }

    result := recursion(nums, len(nums))
    return result
}

func main() {
    nums := []int{1, 2, 3, 4, 5}
    fmt.Println(subsets(nums))
}

What did you expect to see?

[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3],[4],[1,4],[2,4],[1,2,4],[3,4],[1,3,4],[2,3,4],[1,2,3,4],[5],[1,5],[2,5],[1,2,5],[3,5],[1,3,5],[2,3,5],[1,2,3,5],[4,5],[1,4,5],[2,4,5],[1,2,4,5],[3,4,5],[1,3,4,5],[2,3,4,5],[1,2,3,4,5]]

What did you see instead?

[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3],[4],[1,4],[2,4],[1,2,4],[3,4],[1,3,4],[2,3,4],[1,2,3,5],[5],[1,5],[2,5],[1,2,5],[3,5],[1,3,5],[2,3,5],[1,2,3,5],[4,5],[1,4,5],[2,4,5],[1,2,4,5],[3,4,5],[1,3,4,5],[2,3,4,5],[1,2,3,5,5]]

When appending the last item of the array to the subsets[7], in this case whose value is 5, the subsets[15] is also updated!
For debugging purpose, i write the debug code which is commented out above to reproduce this bug. Please , Thank you very much.

seankhliao commented 2 years ago

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

wangfengfly commented 2 years ago

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

I encountered a bug, when appending an item to a 2d slice, this is not a question, but a possible bug, please help and have a look at the issue? thank you

ALTree commented 2 years ago

@wangfengfly sorry, this is a bug in your code, caused by an erroneous understanding of what slices are. Slices are just views over a backing array. When you append to a slice, the backing array changes. Your program has multiple slices sharing the same backing array. Consider:

func main() {
    arr := []int{1, 2, 3, 4, 5}
    slice := arr[0:3]
    fmt.Println(arr) // prints [1 2 3 4 5]
    slice = append(slice, 5)
    fmt.Println(arr) // prints [1 2 3 5 5]
}

This is roughly what's happening in your code. Please see the link above if you have further questions.

ianlancetaylor commented 2 years ago

See https://go.dev/blog/slices-intro .

wangfengfly commented 2 years ago

@wangfengfly sorry, this is a bug in your code, caused by an erroneous understanding of what slices are. Slices are just views over a backing array. When you append to a slice, the backing array changes. Your program has multiple slices sharing the same backing array. Consider:

func main() {
   arr := []int{1, 2, 3, 4, 5}
   slice := arr[0:3]
   fmt.Println(arr) // prints [1 2 3 4 5]
   slice = append(slice, 5)
   fmt.Println(arr) // prints [1 2 3 5 5]
}

This is roughly what's happening in your code. Please see the link above if you have further questions.

Oh, sorry, it is indeed my code fault, thank you very much.

wangfengfly commented 2 years ago

See https://go.dev/blog/slices-intro .

ok, thank you very much.