我有以下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只是前一个函数调用遗留下来的垃圾。
我最后一次遇到这样的问题,是因为我错过了一些编译标志等。对于x64非托管c ++项目,我应该注意哪些设置?还有其他原因我可能会看到这种行为吗?
如果需要,我可以发布更多的反汇编。
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;
}
...
}
...
}
答案 0 :(得分:1)
我在这里向MS发布了一个错误报告: https://connect.microsoft.com/VisualStudio/feedback/details/674672/callee-disassembly-expects-address-which-caller-is-not-providing-in-x64-mode
再次感谢大家的帮助!
答案 1 :(得分:0)
这看起来像VS2010中的same bug Qt people encountered。该报告链接到Microsoft Connect here。还有bug should be fixed in SP1。在SP1中修复了许多优化问题,因此我可能没有链接正确的(发现其他三个只是通过链接筛选)。
答案 2 :(得分:-1)
else if (strchr((char*)Other_Uchar_Table_Of_Enum_Values, myOther32BitType.8BitField)) continue;
这看起来很可怕错误。您应该使用std::find
。
事实上,您的整个代码看起来都充斥着C风格的不安全代码。内存管理对象在哪里?