首页 > 解决方案 > gcc 使用 source == dest 生成 memcpy?

问题描述

调用时memcpy(),我尝试确保源/目标指针不重叠,因为规范说这是未定义的行为。但是,对于下面的简单示例,GCC 会生成一个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 ;
}

使用gcc -O0,我的本地 GCC (5.4.0) 和 godbolt.org GCC x86-64 10.2 生成以下行*p_a = a

call memcpy

(我没有使用-O2,因为这需要更复杂的示例来演示问题)

我问是因为我们有一个嵌入式系统,当memcpy()源/目标重叠时会生成警告。但是,由于上面的示例,有些人希望在 source==dest 时关闭警告。什么是合理的?

标签: cgcc

解决方案


C 标准没有定义memcpy源和目标重叠时的行为这一事实并不意味着 C 编译器不能要求、知道和依赖memcpy它使用的特定对象在源和目标重叠时的行为符合预期的事实。

在这种情况下,唯一的要求memcpy(除了 C 标准的要求)是它在源和目标相同的情况下工作。如果 C 编译器需要memcpy它使用的属性,那么根据 C 标准这是可以的——C 实现可能对其软件有任何内部要求。C 标准仅管理软件的外部行为,而不管理软件内部的工作方式。

这是一个相当温和的要求,不定义源和目标重叠时的行为的原因是memcpy,在写入重叠目标的过程中,可能的各种实现可能会在读取源之前更改部分源。但是,当源和目标相同时,不会发生这种情况,至少在memcpy. 所以这是一个很容易满足的要求。

编译器memcpy生成的代码效率低下,因为它没有净效应,但这无关紧要,因为代码是在禁用优化的情况下生成的。


推荐阅读