memcpyとmemmoveの違い
4613 ワード
昨日大きな失敗をしました.記録しなければなりません.memcpy()とmemmove()の違いは、前にこの2つの違いを知ったことがありますが、仕方なくずっと使っていません.すぐにmemmove()という関数を忘れてしまいました.そのため、少しも印象がなくて、本当にその言葉を証明して、使わないのは役に立たないに等しい.
1.ソースパス
ネット上の多くの文章はこれらの標準ライブラリの方法について大体話して、いくつかの細部は隠して、私はやはりソースコードの出所を見つけることに慣れて、自分で更に他の人の文章によって理解します.この2つの関数はglibcで実現され、glibcのソースコードを自分でダウンロードすることができます.
2.ソースコード
ソースコードは分かりやすいように見えますが、memcpy()はdstppとsrc ppが指す空間サイズが重なるかどうかを判断していません.重なると、後からコピーしたデータが前のデータの一部を上書きし、データエラーが発生します.memmove()は、ソースアドレスと宛先アドレスが重複しない場合はmemcpy()を呼び出し、そうでなければ後置コピーを行い、アドレスが指すメモリ空間の最後から前へコピーすると判断した.
BYTE_COPY_FWD、 WORD_COPY_FWD、WORD_COPY_BWD、BYTE_COPY_BWDは、マクロの名前からバイトのプリアンブル、ワードのプリアンブル、ワードの後置コピー、バイトの後置コピーであることがわかり、コンパイルの最適化が行われているそうです.
3.まとめ
後でmemmove()関数を使いましょう.memcpy()は使いません.
1.ソースパス
ネット上の多くの文章はこれらの標準ライブラリの方法について大体話して、いくつかの細部は隠して、私はやはりソースコードの出所を見つけることに慣れて、自分で更に他の人の文章によって理解します.この2つの関数はglibcで実現され、glibcのソースコードを自分でダウンロードすることができます.
glibc/string/memmove.c
glibc/string/memcopy.c
2.ソースコード
#include
#include
#undef memcpy
void *
memcpy (void *dstpp, const void *srcpp, size_t len)
{
unsigned long int dstp = (long int) dstpp;
unsigned long int srcp = (long int) srcpp;
/* Copy from the beginning to the end. */
/* If there not too few bytes to copy, use word copy. */
if (len >= OP_T_THRES)
{
/* Copy just a few bytes to make DSTP aligned. */
len -= (-dstp) % OPSIZ;
BYTE_COPY_FWD (dstp, srcp, (-dstp) % OPSIZ);
/* Copy whole pages from SRCP to DSTP by virtual address manipulation,
as much as possible. */
PAGE_COPY_FWD_MAYBE (dstp, srcp, len, len);
/* Copy from SRCP to DSTP taking advantage of the known alignment of
DSTP. Number of bytes remaining is put in the third argument,
i.e. in LEN. This number may vary from machine to machine. */
WORD_COPY_FWD (dstp, srcp, len, len);
/* Fall out and copy the tail. */
}
/* There are just a few bytes to copy. Use byte memory operations. */
BYTE_COPY_FWD (dstp, srcp, len);
return dstpp;
}
libc_hidden_builtin_def (memcpy)
#include
#include
/* All this is so that bcopy.c can #include
this file after defining some things. */
#ifndef a1
#define a1 dest /* First arg is DEST. */
#define a1const
#define a2 src /* Second arg is SRC. */
#define a2const const
#undef memmove
#endif
#if !defined(RETURN) || !defined(rettype)
#define RETURN(s) return (s) /* Return DEST. */
#define rettype void *
#endif
#ifndef MEMMOVE
#define MEMMOVE memmove
#endif
rettype
inhibit_loop_to_libcall
MEMMOVE (a1const void *a1, a2const void *a2, size_t len)
{
unsigned long int dstp = (long int) dest;
unsigned long int srcp = (long int) src;
/* This test makes the forward copying code be used whenever possible.
Reduces the working set. */
if (dstp - srcp >= len) /* *Unsigned* compare! */
{
/* Copy from the beginning to the end. */
#if MEMCPY_OK_FOR_FWD_MEMMOVE
dest = memcpy (dest, src, len);
#else
/* If there not too few bytes to copy, use word copy. */
if (len >= OP_T_THRES)
{
/* Copy just a few bytes to make DSTP aligned. */
len -= (-dstp) % OPSIZ;
BYTE_COPY_FWD (dstp, srcp, (-dstp) % OPSIZ);
/* Copy whole pages from SRCP to DSTP by virtual address
manipulation, as much as possible. */
PAGE_COPY_FWD_MAYBE (dstp, srcp, len, len);
/* Copy from SRCP to DSTP taking advantage of the known
alignment of DSTP. Number of bytes remaining is put
in the third argument, i.e. in LEN. This number may
vary from machine to machine. */
WORD_COPY_FWD (dstp, srcp, len, len);
/* Fall out and copy the tail. */
}
/* There are just a few bytes to copy. Use byte memory operations. */
BYTE_COPY_FWD (dstp, srcp, len);
#endif /* MEMCPY_OK_FOR_FWD_MEMMOVE */
}
else
{
/* Copy from the end to the beginning. */
srcp += len;
dstp += len;
/* If there not too few bytes to copy, use word copy. */
if (len >= OP_T_THRES)
{
/* Copy just a few bytes to make DSTP aligned. */
len -= dstp % OPSIZ;
BYTE_COPY_BWD (dstp, srcp, dstp % OPSIZ);
/* Copy from SRCP to DSTP taking advantage of the known
alignment of DSTP. Number of bytes remaining is put
in the third argument, i.e. in LEN. This number may
vary from machine to machine. */
WORD_COPY_BWD (dstp, srcp, len, len);
/* Fall out and copy the tail. */
}
/* There are just a few bytes to copy. Use byte memory operations. */
BYTE_COPY_BWD (dstp, srcp, len);
}
RETURN (dest);
}
#ifndef memmove
libc_hidden_builtin_def (memmove)
#endif
ソースコードは分かりやすいように見えますが、memcpy()はdstppとsrc ppが指す空間サイズが重なるかどうかを判断していません.重なると、後からコピーしたデータが前のデータの一部を上書きし、データエラーが発生します.memmove()は、ソースアドレスと宛先アドレスが重複しない場合はmemcpy()を呼び出し、そうでなければ後置コピーを行い、アドレスが指すメモリ空間の最後から前へコピーすると判断した.
BYTE_COPY_FWD、 WORD_COPY_FWD、WORD_COPY_BWD、BYTE_COPY_BWDは、マクロの名前からバイトのプリアンブル、ワードのプリアンブル、ワードの後置コピー、バイトの後置コピーであることがわかり、コンパイルの最適化が行われているそうです.
3.まとめ
後でmemmove()関数を使いましょう.memcpy()は使いません.