-2

I do understand that it's generally unsafe to memcpy to overlapping regions and I do understand the reasons. But my question is: is it generally safe to do something like that?

#include <stdio.h>
#include <string.h>

int main(void) {
    int a = 5;
    memcpy(&a, &a, sizeof a);
    printf("%d", a);
    return 0;
}

If not, in which hardware/software configurations can I assume it to be safe?

edit1: so I'll refine my question: would the usual* implementation of this function consider it safe? (outside of C standards of course)

edit2: I do know the problem could be solved easily, but the question aroused by the strange use case, which is not directly covered by other answers.

*for usual I mean the implementation of most used and deployed systems (e.g. linux, windows ...)

Jk1
  • 11,233
  • 9
  • 54
  • 64
iosonome
  • 29
  • 1
  • 5
  • 5
    Any reason not to use [memmove](http://man7.org/linux/man-pages/man3/memmove.3.html)? – Adrian Panasiuk Jun 21 '14 at 08:54
  • 2
    It's undefined behavior. – Michael Burr Jun 21 '14 at 08:58
  • 2
    Yeah, I'm not sure of the purpose of this question. The language standard declares this to be undefined behaviour, and there's already a trivial solution (`memmove`). There may be particular compiler/hardware combinations where this will work, but it won't be portable. – Oliver Charlesworth Jun 21 '14 at 08:58
  • 1
    You realize that doesn't actually accomplish anything useful? – CDahn Jun 21 '14 at 08:59
  • Not sure why this is downvoted. It's a legitimate question, though _it might be_ duplicate. –  Jun 21 '14 at 09:06
  • @Tibor: If it's a duplicate, please vote to close as a duplicate! – Oliver Charlesworth Jun 21 '14 at 09:06
  • 2
    @Tibor I would consider this a bad question, since documentation for memcpy is everywhere. – this Jun 21 '14 at 09:08
  • This very same question hasn't be asked actually. – iosonome Jun 21 '14 at 09:10
  • @Adrian Panasiuk I have a function that will copy to 2 different locations in all case but 1, and I was thinking if I'd better adding a test, switching to memmove or I could just assume it to be safe. – iosonome Jun 21 '14 at 09:12
  • Regarding your edit: as suggested in other comments - why not just use `memmove()`? Or if you really have something against `memmove()` put the `memcpy()` call in an `if` that tests for the pointers being different (I'm assuming that for your use case, the blocks will not overlap if the pointers are different). Use one of these options, and you don't have to worry about whether or not the implementation will handle things the way you want, now and in the future. You can start worrying about more important things that don't have ready solutions. – Michael Burr Jun 21 '14 at 09:26
  • @MichaelBurr I know i can solve the problem easily, the question arouse just for the unusual case. – iosonome Jun 21 '14 at 09:28
  • @iosonome: your edit about "would the usual implementation of this function consider it safe" came after many answers indicating the call would not be safe. Even if you find that things seem to work today on whatever implementation you're using, they might not work tomorrow when the compiler gets updated or different options get used. Who knows, with UB even changing a variable name might trigger bad behavior: http://stackoverflow.com/questions/4575697/unexpected-output-from-bubblesort-program-with-msvc-vs-tcc/4577565#4577565 I'll bet you would never have guessed that (I sure wouldn't have). – Michael Burr Jun 21 '14 at 09:43

3 Answers3

9

From the C standard:

#include <string.h>
void *memcpy(void * restrict s1,
          const void * restrict s2,
          size_t n);

The memcpy function copies n characters from the object pointed to by s2 into the object pointed to by s1. If copying takes place between objects that overlap, the behavior is undefined.

Since a overlaps with a in its entirety, this code is not ever safe, and you can never assume that it is safe.


It may be safe on some combination of platforms and compilers, but you still can't assume that it is safe, you would have to find some documentation guaranteeing that it has some particular behaviour.

Mankarse
  • 39,818
  • 11
  • 97
  • 141
  • 2
    Moreover, the first two arguments of memcpy() have the restrict qualifier, unlike memmove(). This means that aliasing cannot happen in memcpy() and the function should not be used with overlapping areas. – Christophe Vu-Brugier Jun 21 '14 at 09:14
1

Is it safe to memcpy to the exact same region?

No. This will invoke undefined behavior. The source of copy and destination must not overlap.

memcpy has following prototype in C99:

void *memcpy(void *restrict s1, const void *restrict s2, size_t n);

The use of restrict with both s1 and s2 indicates that the source of the copy and destination shouldn't overlap. (It doesn't guarantee that they do not overlap).

haccks
  • 104,019
  • 25
  • 176
  • 264
0

I would strongly advise against depending on undefined behaviour, regardless of whether the code is intended to run on only one platform. C optimizers are known for taking advantage of undefined behavior and an update to your C compiler is all it takes to break your code.

To read more about the dangers of depending on undefined behavior (includes examples), read Towards Optimization-Safe Systems: Analyzing the Impact of Undefined Behavior. Xi Wang, Nickolai Zeldovich, M. Frans Kaashoek, and Armando Solar-Lezama.

Adrian Panasiuk
  • 7,249
  • 5
  • 33
  • 54