-
Notifications
You must be signed in to change notification settings - Fork 17.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
bytes: copying Buffer struct corrupts content #26462
Comments
Change https://golang.org/cl/122595 mentions this issue: |
CL 122518 rolled back an earlier CL that made "go test" start running test binaries for packages with no *_test.go files. Add a test as another roadblock to reintroducing that behavior in the future. For golang#26462. Change-Id: I898103064efee8d6ae65bcf74f4dffc830eae7e9 Reviewed-on: https://go-review.googlesource.com/122595 Run-TryBot: Russ Cox <rsc@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org>
Is it safe to assume that bytes.Buffer struct can be copied just like? I do not see a test doing that in buffer_test.go. I see that there is a function Your example using that function: https://play.golang.org/p/sByMPpES47e |
If copying buffers wasn't supported by design, it should probably be caught by vet via the |
I know the If we add more print statements to the example (https://play.golang.org/p/Tt1p4CyhsPp):
Output is:
Between the
Nothing else, yet the content of the buffers change. |
When you do |
Maybe documentation should be improved for such a case? Or vet rule added? |
@bontibon I think that explains everything, thanks. @ysmolsky Vet rule would be definitely useful for such cases. |
See previously #25907, and I could have sworn that @alandonovan filed a similar issue (for a vet or lint check) but I can't find it now. |
@bontibon When you do b := a, b.buf is a slice of a.bootstrap. Can you explain the principle to me in detail? |
A bytes.Buffer is an example of a data structure that contains a pointer to its own interior. (In the specific case of Buffer, its buf field is a slice that initially points to a small array called bootstrap.) In general it is not safe to copy such a value without additional logic. (This is the purpose of a "copy constructor" in C++, but Go does not have that concept.) Otherwise, the copy and the original become entangled as both point into the interior of the original; operations on one variable may be observed by the other variable, or have unpredictable effects. Go programmers should defensively assume that it is not safe to make a copy of any value of type T whose methods are associated with the pointer, *T. |
Buffer.bootstrap is now gone: 9c2be4c. |
Fixed, so closing. Thanks. |
Please answer these questions before submitting your issue. Thanks!
What version of Go are you using (
go version
)?go version go1.10.3 linux/amd64
Does this issue reproduce with the latest release?
Yes
What operating system and processor architecture are you using (
go env
)?GOARCH="amd64"
GOBIN=""
GOCACHE="/home/icza/.cache/go-build"
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/home/icza/gows"
GORACE=""
GOROOT="/usr/local/go"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build608842240=/tmp/go-build -gno-record-gcc-switches"
What did you do?
Run the following app https://play.golang.org/p/8XAMVW4UZd7
What did you expect to see?
Since
bytes.Buffer
is a struct (holding a slice buffer and some other fields), assigning the struct value should copy all the fields (including the slice buffer - the slice header), so content should not change, and the result struct should give the same content whenString()
is called on it.What did you see instead?
The text was updated successfully, but these errors were encountered: