memcpyやmemcmpで構造体を処理して良いか?

実装例をよく見ますが、仕様からするとNoです。

そんなの当たり前でしょ、という方はこれ以上読む必要はありません。時と場合によるだろ、と思ってる方は一応読んでみてください。



memcpyとmemcmpは連続したメモリに対する操作です。

構造体(struct)において、メモリには宣言どおりに並ぶ事が保証されています。しかし、同時にコンパイラがアライメントを揃える事も許可しています。順番は並び替えなくても、間に何もいれない保証はないのです。

具体例を挙げましょう。intが4バイトの処理系で以下の構造体のsizeofはいくつになると思いますか?

struct test_t {

    char a;
    int  b;

};

Visual C++ .NET 2003でコンパイルしたら、になりました。つまり、aとbの他に見えない3バイト分のゴミが入ります。理由は省略しますが、この構造体は、ゴミがコピー(memcpy)されたり、比較(memcmp)されたりするわけです。ちなみに、パディングされるバイト数はその処理系で都合の良い数がはいります。

結果として、構造体のデータとは関係ない比較結果が返されます。

また、以下の原因により、正しく動作したように勘違いする可能性があります。

  • 構造体を最初にmemsetで0クリアする
  • 構造体にポインタが含まれない
  • アライメントの調整(パディング)が行われない

ここら辺を間違っていた方は、一度基礎からやり直すことをお勧めします。



(05/12/30) 友人指摘により、一部修正。他の指摘として、memcmpは他の説明もするべきで、この理由だけでは不適切との事。暫し考慮中。

Leave a Reply

最初のコメントを頂けますか?

更新通知を受け取る »
avatar
wpDiscuz