古典的なmemcpyは関数の引数としてCの配列を持っています。下で指摘したように、私は自分のコードに誤りがありますが、間違ったコードはローカルコンテキストで動作しました!memcpyが単純なオブジェクトのローカル配列メンバにコピーできないのはなぜですか?
私は、オブジェクトを使用してMacintoshピクチャオペコードの再生をエミュレートしている移植ジョブでこの奇妙な動作を検出しました。私のDrawStringオブジェクトは明らかに文字列引数のコピーに失敗したため、再生時にガベージを描画していました。以下は、私が書いたテストケースです。手動コピーループは動作しますが、memcpyは失敗することに注意してください。 Visual Studioデバッガでのトレースは、memcpyが宛先をゴミでオーバーライトしていることを示しています。
Memcpyは2つのローカルStr255アレイで正常に動作します。
スタック上のオブジェクトの1つがメンバである場合、失敗します(他のテストでは、オブジェクトがヒープ上にあるときにも失敗します)。
次のサンプルコードは、演算子=で呼び出されたmemcpyを示しています。私はコンストラクタで失敗した後にそこに移動しましたが、違いはありませんでした。
typedef unsigned char Str255[257];
// snippet that works fine with two local vars
Str255 Blah("\004Blah");
Str255 dest;
memcpy(&dest, &Blah, sizeof(Str255)); // THIS WORKS - WHY HERE AND NOT IN THE OBJECT?
/*!
class to help test CanCopyStr255AsMember
*/
class HasMemberStr255 {
public:
HasMemberStr255()
{
mStr255[0] = 0;
}
HasMemberStr255(const Str255 s)
{
for (int i = 0; i<257; ++i)
{
mStr255[i] = s[i];
if (s[i]==0)
return;
}
}
/// fails
void operator=(const Str255 s) {
memcpy(&mStr255, &s, sizeof(Str255));
};
operator const Str255&() { return mStr255; }
private:
Str255 mStr255;
};
-
/*!
Test trivial copying technique to duplicate a string
Added this variant using an object because of an apparent Visual C++ bug.
*/
void TestMacTypes::CanCopyStr255AsMember()
{
Str255 initBlah("\004Blah");
HasMemberStr255 blahObj(initBlah);
// using the operator= which does a memcpy fails blahObj = initBlah;
const Str255& dest = blahObj; // invoke cast operator to get private back out
CPPUNIT_ASSERT(dest[0]=='\004');
CPPUNIT_ASSERT(dest[1]=='B');
CPPUNIT_ASSERT(dest[2]=='l');
CPPUNIT_ASSERT(dest[3]=='a');
CPPUNIT_ASSERT(dest[4]=='h');
CPPUNIT_ASSERT(dest[5]=='\0'); // trailing null
}
どのように失敗しますか? – sharptooth
私が言ったように、私はmemcpyを使用するとゴミで上書きされます –
バグは決してコンパイラにはありません。 –