Thursday, February 3, 2022

[SOLVED] gcc generates memcpy with source == dest?

Issue

When calling memcpy(), I try to make sure the source/dest pointers do not overlap because the specification says that is undefined behavior. For the following simple example, though, GCC generates a memcpy() with source == dest.

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

struct my_struct {
  int a[5000] ;
} ;

int main(void)
{
  struct my_struct a ;
  struct my_struct *p_a = &a ;
  memset( &a, 0, sizeof(a) ) ;

  *p_a = a ;
  printf("%d\n",p_a->a[10] );

  return 0 ;
}

Using gcc -O0, both my local GCC (5.4.0) and godbolt.org GCC x86-64 10.2 produce the following line for *p_a = a:

call memcpy

(I'm not using -O2 because that would require a more complicated example to demonstrate the problem)

I'm asking because we have an embedded system that generates a warning when memcpy() source/dest overlap. However, some people want to turn off the warning if source==dest because of the above example. What's reasonable?


Solution

The fact that the C standard does not define the behavior of memcpy when the source and destination overlap does not mean a C compiler cannot require, know, and rely on the fact that the particular memcpy it uses behaves as desired when the source and destination overlap.

In this case, the only requirement upon memcpy (beyond that of the C standard) is that it work when the source and destination are the same. If a C compiler requires that property for the memcpy it uses, that is fine by the C standard—a C implementation may have whatever internal requirements for its software it desires. The C standard governs only the external behavior of the software, not how it works internally.

And this is a fairly mild requirement, the reason for not defining the behavior when the source and destination overlap is that various implementations of memcpy might, in the course of writing to an overlapping destination, alter parts of the source before they have been read. However, this does not occur when the source and destination are identical, at least not in normal implementations of memcpy. So it is an easy requirement to fulfill.

The memcpy generated by the compiler is inefficient, since it has no net effect, but that is of no concern since the code was generated with optimization disabled.



Answered By - Eric Postpischil
Answer Checked By - Dawn Plyler (WPSolving Volunteer)