0

C言語でmemcpyを使った以下のような配列コピーのコードで
以下のコードではbufの先頭アドレスから一つずらしたところにコピーすることで、コピー先とコピー元をあえて重複させて未定義動作を引き起こそうと思ったのですが。

・これは適切な未定義動作の例になっているのか自分でもよくわかりません。またこれがなぜこのような結果になるのか簡単にでも教えていただきたいです。
・また見様見真似で書いたコードなのですがもっと簡単なコードがあればぜひ教えていただきたいです

#include <stdio.h>
#include <string.h>

void* memcpy(void dst,const void src,size_t n){ size_t i; char p1=dst; const char p2=src;

    for(i=0;i&lt;n;++i){
            *p1=*p2;
            ++p1;
            ++p2;
    }

}

int main(void){ char buf[]={0,1,2,3,4}; char buf2[5];

    memcpy(buf+1,buf,sizeof(buf));

    for(int i=0;i&lt;sizeof(buf);++i){
            printf(&quot;%d\n&quot;,buf[i]);
    }

    return 0;

}

結果は以下のようになりました。

0
0
1
2
3
*** stack smashing detected ***: <unknown> terminated
Aborted (core dumped)
sayuri
  • 42,863
  • 1
  • 33
  • 94
yoshida
  • 21
  • 2
  • 未定義動作は、文字通りどういう動作になるか何も定義されていないので、その結果について聞くのは無意味な事です。何でもありです。[Old New Thing: 未定義動作はタイムトラベルを引き起こす] https://cpplover.blogspot.com/2014/06/old-new-thing.html – radian Nov 16 '21 at 02:52

1 Answers1

1

提示コードに関しては立派な未定義動作を引き起こしています。

  • buf[5] に書き込んでいる
  • 標準組み込み関数 memcpy と同名の関数を自分で定義している

専門用語「未定義の動作」に関しては例えば C : 配列の添字について 参照。よって未定義動作をするプログラムはあなたの勝手な期待通りに動くとは限りません。実際 Visual Studio 2019 Version 16.11.6 の [c++] x86 Debug Build では 0 0 0 0 0 表示となってデバッガに Run-Time Check Failure #2 - Stack around the variable 'buf' was corrupted. となりました。事後にメモリ破壊が検出されたということのようです。

適切な未定義動作の例になっているのか自分でもよくわかりません

未定義動作は不適切なプログラムが起こすものなので「適切な未定義動作」なんてものはないです。最近の賢いコンパイラなら

int main() {
    char buf[5];
    buf[5]='\0';
}

だけでも十分エラー検出してくれます。が、昔ながらの組み込み系コンパイラだとこの辺はコンパイル時にも実行時にも何の検出も行わずにただメモリ破壊を行うのみだったりします(上記コードはスタック上の未使用領域を壊すだけで無害だったりするので、検出が困難でたちが悪いっス。

774RR
  • 21,855
  • 19
  • 44