Classic memcpy gotcha с массивами C в качестве аргументов функции. Как указано ниже, у меня есть ошибка в моем коде, но ошибочный код работал в локальном контексте!Почему memcpy не копирует локальный элемент массива простого объекта?
Я только что столкнулся с этим странным поведением в задании портирования, где я эмулирую воспроизведение кода opcode Macintosh с использованием объектов. Мой объект DrawString рисовал мусор при воспроизведении, потому что он, по-видимому, не смог скопировать аргумент строки. Следующее - это тестовый сценарий, который я написал, - обратите внимание, как работает цикл копирования вручную, но memcpy терпит неудачу. Трассировка в отладчике Visual Studio показывает, что memcpy создает назначение с мусором.
Memcpy на двух локальных строках Str255 отлично работает.
Когда один из них является членом объекта в стеке, он терпит неудачу (в другом тестировании он также терпит неудачу, когда объект находится в куче).
Следующий пример кода показывает, что memcpy вызывается в operator =. Я переместил его туда после того, как он потерпел неудачу в конструкторе, но не было никакой разницы.
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. –
Ошибка в компиляторе. –