У меня есть следующая функция MyType::Is_Inst ()
, которая выдает ошибку доступа к недопустимой памяти при возврате в 64-битном режиме, но не в 32-битном:
MyType MyType::Is_Inst () {
unsigned char Bar=0;
MyType Foo={0};
return Foo;
}
Глядя на разборки + пошаговое выполнение программы на линии
mov dword ptr [rax],ecx
... когда программа в основном пытается разыменовать исходное значение% rdx (с момента первого вызова функции), которое теперь находится в% rax. Тем не менее,% rdx - это просто мусор, оставшийся после предыдущего вызова функции.
В прошлый раз у меня была такая проблема, потому что я пропускал некоторые флаги компиляции или тому подобное. Существуют ли какие-либо настройки, о которых мне следует знать для неуправляемых проектов C ++ x64? Есть ли другие причины, по которым я могу видеть это поведение?
Я могу опубликовать больше разборок, если вам это нужно.
Определение класса для MyType выглядит следующим образом:
class __declspec(dllexport) MyType {
public:
union {
struct {
unsigned int Id : 23;
unsigned int Flag : 1;
unsigned int Type : 4;
unsigned int Unused : 4; /* 32 bits total */
};
unsigned int All_Bits; /* Full 32 bits of MyType */
};
/* There are some function definitions here, but no other
variables, aside from some statically defined ones. */
};
ОБНОВЛЕНИЕ: Это более лаконичная, оптимизированная версия разборки Is_Inst (), которая показывает проблему. Для краткости я удалил старую версию, которая была здесь раньше.
// MyType MyType::Is_Inst () {
// uchar Bar=0;
// MyType Foo={0};
mov dword ptr [rdx],0 /* %rdx is 0x17, from a prev fn call. */
// return Foo;
mov rax,rdx
// }
ret
Код, вызывающий вызов Is_Inst ():
...
for (Counter=0; Counter<N_Items; Counter++) {
...
myOther32BitType = arrayOfMyOtherTypes [Counter]; /* Debugger shows this is ok. */
if (myOther32BitType.8BitField==UNEQUAL_ENUM_VALUE) {
/* Some stuff that doesn't happen. */
}
/* myOther32BitType.8BitField==0x17, so %rdx gets set to 0x17. */
else if (strchr((char*)Uchar_Table_Of_Enum_Values, myOther32BitType.8BitField)) continue;
/* %rdx gets set to 0x17 again. */
else if (strchr((char*)Other_Uchar_Table_Of_Enum_Values, myOther32BitType.8BitField)) continue;
else if ( myOther32BitType.8BitField==EQUAL_ENUM_VALUE) {
if (myType.Is_Inst ().All_Bits) { /* Is_Inst() called here. */
return false;
}
...
}
...
}