Skip to content
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

spec: does append use memmove like copy? #4142

Closed
rsc opened this issue Sep 24, 2012 · 3 comments
Closed

spec: does append use memmove like copy? #4142

rsc opened this issue Sep 24, 2012 · 3 comments
Assignees
Milestone

Comments

@rsc
Copy link
Contributor

@rsc rsc commented Sep 24, 2012

From a discussion on golang-nuts.

The spec defines that copy behaves as C's memmove, so that
    copy(x[1:], x[2:])
    x = x[:len(x)-1]
is a correct implementation of deleting x[1] from x.

However, some people are writing
    x = append(x[:1], x[2:]...)
which apparently works too, but I don't believe the spec guarantees this. Should we say
something about append where the source and destination overlap?
@griesemer
Copy link
Contributor

@griesemer griesemer commented Sep 26, 2012

Comment 1:

I think we should say something, the question is what to say. There are two answers:
1) append does not make any guarantees for overlapping operands (status quo explicitly
spelled out).
2) append does "the right thing" (like copy) for overlapping operands.
If we spell out 1), users may still rely on the concrete behavior of a particular
implementation (which may happen to do 2). If a another implementation behaves
differently, it will lead to very hard to find bugs. Thus, I am inclined to spell out 2).

@robpike
Copy link
Contributor

@robpike robpike commented Sep 26, 2012

Comment 2:

I am the person (or at least one of the people) who proposed to the
ANSI C standards committee to make memcpy work right in the case of
overlap. Even though we got memmove instead, it's at least possible to
use memmove everywhere and know your program won't break. I haven't
used memcpy since.
In that spirit, I vote strongly for option 2.
-rob
P.S. I also proposed making malloc(0) perfectly fine, since zero is a
perfectly fine value. I also, in the same letter, proposed making
zero-sized arrays legal, mostly so you could do the extend-the-struct
trick for a variable-sized array as the last field of the struct. I
got two letters back as answer to my one. #1: Malloc(0) shouldn't work
because zero-sized arrays don't work. #2: Zero-sized arrays shouldn't
work because malloc(0) doesn't work. Well played, ANSI C committee,
and may your lives be a living hell.
P.P.S. Once ANSI C came out, memmove was required to work but memcpy
wasn't, so we just used memmove everywhere (and so should you). We
noticed though that some of our code was extremely slow when compiled
on IRIX. We dug in, and found that, rather than using an if statement
to solve the overlap problem, the implementers of memmove fixed the
problem by implementing memmove with a correct but remarkable
technique, regardless of actual overlap: 1. malloc a buffer. 2. memcpy
source to buffer. 3. memcpy buffer to destination. 4 free buffer. The
best-laid plans and all that.

@griesemer
Copy link
Contributor

@griesemer griesemer commented Sep 28, 2012

Comment 3:

This issue was closed by revision 0c49471.

Status changed to Fixed.

@rsc rsc added fixed labels Sep 28, 2012
@rsc rsc added this to the Go1.1 milestone Apr 14, 2015
@rsc rsc removed the go1.1maybe label Apr 14, 2015
@golang golang locked and limited conversation to collaborators Jun 24, 2016
This issue was closed.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
4 participants