carloscn / structstudy

Leetcode daily trainning by using C/C++/RUST programming.
4 stars 1 forks source link

user01:实现库函数memmove(memmove implementation) #151

Open carloscn opened 1 year ago

carloscn commented 1 year ago

问题描述

对于man手册中memcpy的接口,有一条这样的说明,https://man7.org/linux/man-pages/man3/memcpy.3.html

void *memcpy(void *restrict dest, const void *restrict src, size_t n);

NOTES:
       Failure to observe the requirement that the memory areas do not
       overlap has been the source of significant bugs.  (POSIX and the
       C standards are explicit that employing memcpy() with overlapping
       areas produces undefined behavior.)  Most notably, in glibc 2.13
       a performance optimization of memcpy() on some platforms
       (including x86-64) included changing the order in which bytes
       were copied from src to dest.

       This change revealed breakages in a number of applications that
       performed copying with overlapping areas.  Under the previous
       implementation, the order in which the bytes were copied had
       fortuitously hidden the bug, which was revealed when the copying
       order was reversed.  In glibc 2.14, a versioned symbol was added
       so that old binaries (i.e., those linked against glibc versions
       earlier than 2.14) employed a memcpy() implementation that safely
       handles the overlapping buffers case (by providing an "older"
       memcpy() implementation that was aliased to [memmove(3)]

memcpy对同一个buffer会出现内存覆盖的现象,请你实现memmove的逻辑,来解决同一个数组的内存覆盖问题。

carloscn commented 1 year ago

问题分析

这道题目需要进行两种情况的分析,分析板书过程如下:

IMG_0346

void* utils_memmove(void *dest, const void *src, size_t n)
{
    uint8_t *from = (uint8_t *) src;
    uint8_t *to = (uint8_t *) dest;

    if (from == to || 0 == n) {
        return dest;
    }

    if (to > from && to - from < (int)n) {
        /* to overlaps with from */
        /*  <from......>         */
        /*         <to........>  */
        /* copy in reverse, to avoid overwriting from */
        int32_t i;
        for (i = n - 1; i >= 0; i --) {
            to[i] = from[i];
        }

        goto finish;
    }

    if (from > to && from - to < (int)n) {
        /* to overlaps with from */
        /*        <from......>   */
        /*  <to........>         */
        /* copy forwards, to avoid overwriting from */
        size_t i;
        for (i = 0; i < n; i ++) {
            to[i] = from[i];
        }

        goto finish;
    }

    memcpy(dest, src, n);
finish:
    return dest;
}
carloscn commented 1 year ago

code

https://review.gerrithub.io/c/carloscn/structstudy/+/551174/4/c_programming/utils/utils.c