- ベストアンサー
「memcpy」と「strcpy」について
C言語の初心者です。 先日、課題として以下のようなことを言われました。 「memcpyとstrcpyについて、メモリ破壊が起こるとしたら どんな場合が考えられるか、簡単にまとめて報告してみて下さい。」 と言われました。 私にはメモリ破壊というニュアンスが分からないのですが、 どちらの関数も必要以上にコピーを行ったときに 起こるメモリ破壊ということなのでしょうか? それとも、何か特別な意味があるのでしょうか? C言語に詳しい方がいましたら、是非、教えて下さい。 宜しくお願いします。
- みんなの回答 (5)
- 専門家の回答
質問者が選んだベストアンサー
- ベストアンサー
メモリ破壊とは、「当然そこに入っているべき値」を、不用意に上書きしてしまうことです。 たとえば、char a[100]; という宣言をしたとします。 memcpy( a, 0, 200 ); すると、このような実行を行った場合、変数 a の後ろにどんなメモリが存在しているのかプログラマは知ることができないのに、変数 a の後ろの未定メモリ100バイトを上書きしてしまいます。 この未定メモリには、もしかしたら別の変数があるかもしれませんし、プログラムの一部があるかもしれません。あるいはOSのシステム領域かもしれません。 どのみちプログラムは正常に動かなくなります。 通常はメモリエラーが出て停止しますが、最悪の場合、メモリ上のOSを破壊してリセットするしかなくなったりもします。 これがメモリ破壊です。
その他の回答 (4)
- TMINET
- ベストアンサー率32% (45/140)
蛇足的な話ですが strcpyは文字列のコピーですから当然文字列しか引数に指定できない訳ですがmemcpyはメモリ領域のコピーなのでコピーするデータの型を制限しません。 よってデータ型の違うものでもコピー出来てしまいます。 データ型によって確保されるサイズが違いますからコピーしても意図したデータがコピーできないとか、そのデータ型では認識できないデータになるなどmemcpyの使用時の注意も覚えておくといいと思いますよ。 なんでもかんでもmemcpy使うって人は特に...。
memcpy()とstrcpy()はオーバーラップしたメモリを複製するときに問題が生じる場合があります。例えば "0123456789abcdef" の "0123456789ab" を -----^ の位置に複製したい場合に int main() { char source[] = "0123456789abcdef"; char *dist = &source[4]; memcpy(dist, source, 12); dist[12] = '\0'; printf("%s\n", dist); exit(0); } とmemcpy()やstrcpy()を使うとオーバーラップした "456789ab"の部分が破壊され、結果 "012301230123"という結果を得ることになってしまいます。 ただしこれはプラットフォームに(というかlibcの実装)に依存する話で、FreeBSDのmemcpy()はこの問題を再現しますが、Mac OS Xのmemcpy()は安全にコピーできたりします。 また、memcpy()には代替があって理由が無い限りmemmove()をいつでも使えというのがお約束です。 とこの辺のことは全部マニュアルに書いてます。 % man 3 memcpy と質題者がオーバーフローを期待してたら失礼(笑)
お礼
一応、メモリ破壊についてはある程度、理解出来ました。 質問に答えていただき、ありがとうございました。
- jmh
- ベストアンサー率23% (71/304)
char a[5] = "abcd"; strcpy(&a[3], &a[0]); みたいなことをするとダメだったと思います。 char *strcpy(char *dst, const char *src) { whie (*dst++ = *src++) ; return dst; } dst が a[] からハミ出してしまう…。 たぶん…。
お礼
一応、メモリ破壊についてはある程度、理解出来ました。 質問に答えていただき、ありがとうございました。
- news_0203
- ベストアンサー率27% (98/352)
下記のアドレスのサイトを見てみてはいかがでしょうか? 宜しくお願いします。
お礼
ありがとうございました。 1つ確認なのですが、今回の課題の中にあった 「メモリ破壊」というものは、結局 あるアドレスの1部のアドレスを、誤ってコピーする ことにより、突然、全体のメモリが破壊される ということもありえるということでしょうか??
お礼
大変分かりやすい説明をしていただき 本当にありがとうございました。