【问题标题】:Meaning of overlapping when using memcpy使用 memcpy 时重叠的含义
【发布时间】:2017-08-22 14:52:45
【问题描述】:

我正在尝试理解 C 库 <string.h> 中定义的函数 memcpy()

语法:void *memcpy(void*dst,const void*src,size_t n);

我知道这个函数是用来将src指针指向的内存内容复制到dst指针指向的位置,并返回dst指针指向的地址。

我无法理解以下关于memcpy() 的重要声明:

  • 使用memcpy()时,内存地址不能重叠,如果重叠则memcpy()未定义。

另一个查询是: 传递给函数第三个参数的值,即size_t n 始终是整数值吗?

【问题讨论】:

  • 当标准说某些行为是未定义的,这意味着en.wikipedia.org/wiki/Undefined_behavior
  • 这个人告诉你,如果src+n 地址重叠dst dst 中的最终数据可以是任何东西。
  • 对于size_t 看看this SO post
  • “重叠”这个词你不懂吗?
  • 这与内存泄漏无关。如果你在重叠地址使用memcpy,你只会丢失一些数据。

标签: c overlap memcpy


【解决方案1】:

*) memcpy 和 memmove 之间的主要区别在于,memcpy 工作在同一个字符串上,但 memmove 通过获取字符串的副本在单独的内存中工作。
*) 因此,memcpy 中会发生重叠。
让我用一个例子来解释你。
我拿了一个字符数组:

char s[20]="alightechs";

如果我分别做以下操作,

memmove(s+5,s,7);  
memcpy(s+5,s,7); 



o/p for memmove is alighalighte  
o/p for memmove is alighalighal  

因为移动或复制都是逐字节进行的。
直到 alighaligh,这两种情况都没有问题,因为 dest=alite(7 是要复制/移动的字符数),
当 memcpy 我从第 5 位复制时,

alightechs   
alighaechs  
alighalchs  
alighalihs  
alighaligs  
alighaligh  

到这里没有问题,它复制了aligh(5个字母)
因为,memcpy 在同一个字符串上工作,第 6 个字母 将是 a第 7 个字母 将是 l
i.,e 每次更新字符串时都会导致未定义的 o/p,如下所示
在第 6 个字母复制时,
更新后的字符串是 s[20]=alighaligh
所以我们现在得到了

alighaligha  
alighalighal  

【讨论】:

    【解决方案2】:

    从 cmets 来看,您的问题是您不明白“重叠”是什么意思:

    重叠意味着:

    这两个内存区域srcdst 重叠:

    但在这里他们没有:

    所以如果你有重叠的内存区域,那么你不能使用memcpy,但你必须使用memmove


    第二个问题:

    是的,size_t 是无符号整数类型。第三个参数是要复制的字节数,所以它只能是无符号整数类型。

    【讨论】:

    • 我同意图表是最好的答案。
    • 漂亮的图形。建议添加关于memmove() 的评论作为替代。此外,size_t 是一些 unsigned 类型。对于“size_t n 总是一个整数值?”,有些人认为“size_t n 总是一个int?”它不是。
    【解决方案3】:

    memcpy 不使用任何临时内存从 src 复制到 dst

    让我们说:

    • src 开始 @104
    • dst 开始 @108
    • src = "abcdefgh"

    那么 'a' 将是 @104'e' 将是 @108

    假设 char 为 1 字节,然后在复制后:

    • dst = "abcdabcd"

    n 表示要复制的长度,它应该始终是整数。

    要复制重叠区域,可以使用memmove函数,它使用临时内存进行复制。

    【讨论】:

    • 为什么 memmove() 需要一个临时内存区域?一个指针比较将允许复制从适当的结尾开始,以便在读取之前不会覆盖源。
    • C 没有指定memcpy()memmove() 是否使用临时内存。他们可能会,他们可能不会。
    • Linux 程序员手册:memmove() 函数将 n 个字节从内存区 src 复制到内存区 dest。内存区域可能会重叠:复制就像首先将 src 中的字节复制到不与 src 或 dest 重叠的临时数组中一样,然后将字节从临时数组复制到 dest。 @ThingyWotsit
    猜你喜欢
    • 2014-10-27
    • 1970-01-01
    • 2014-03-23
    • 2010-12-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多