如何在C中实现重叠检查memcpy

The*_*net 7 c unix pointers memory-management

这是一项学习练习.我试图通过通知用户复制操作在开始之前是通过还是失败来增加memcpy.我最大的问题是以下几点.如果我分配两个每个100字节的char数组,并有两个引用每个数组的指针,我怎么知道我要复制哪个方向?如果我复制从第一个数组到第二个数组的所有内容,我如何确保用户不会覆盖原始数组?

我当前的解决方案将指针的距离与目标数组的大小进行比较.如果介于两者之间的大小比我说的那样会发生覆盖.但如果它在另一个方向上复制怎么办?我有点困惑.

int memcpy2(void *target, void *source, size_t nbytes) {
    char * ptr1 = (char *)target;
    char * ptr2 = (char *)source;


    int i, val;

    val = abs(ptr1 - ptr2);
    printf("%d, %d\n", val, nbytes + 0);
    if (val > nbytes) {
        for (i = 0; i < val; i++){
            ptr1[i] = ptr2[i];
        }
        return 0;  /*success */
    }
    return -1; /* error */
}



int main(int argc, char **argv){

  char src [100] = "Copy this string to dst1";
  char dst [20];
  int p;
  p = memcpy2(dst, src, sizeof(dst));

    if (p == 0)
        printf("The element\n'%s'\nwas copied to \n'%s'\nSuccesfully\n", src, dst);
    else
        printf("There was an error!!\n\nWhile attempting to copy the elements:\n '%s'\nto\n'%s', \n Memory was overlapping", src, dst);
    return 0;


}
Run Code Online (Sandbox Code Playgroud)

R..*_*R.. 10

确定两个内存范围是否重叠的唯一可移植方法是:

int overlap_p(void *a, void *b, size_t n)
{
    char *x = a, *y =  b;
    for (i=0; i<n; i++) if (a+i==b || b+i==a) return 1;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这是因为指针与关系运算符的比较是未定义的,除非它们指向同一个数组.实际上,这种比较确实适用于大多数实际的实现,因此您可以执行以下操作:

int overlap_p(void *a, void *b, size_t n)
{
    char *x = a, *y =  b;
    return (a<=b && a+n>b) || (b<=a && b+n>a);
}
Run Code Online (Sandbox Code Playgroud)

我希望我的逻辑正确; 你应该检查一下.如果你想假设你可以采取任意指针的差异,你可以进一步简化它.

  • @R - 如果第二个代码示例使用`x`和`y`而不是`a`和`b`? (3认同)