C++ 使旧代码x64兼容时出现非法读/写错误
我有以下C++ 使旧代码x64兼容时出现非法读/写错误,c++,visual-studio-2010,64-bit,unmanaged,C++,Visual Studio 2010,64 Bit,Unmanaged,我有以下MyType::Is_Inst()函数,该函数在返回时以64位模式抛出无效内存访问错误,而不是32位模式: MyType MyType::Is_Inst () { unsigned char Bar=0; MyType Foo={0}; return Foo; } 查看反汇编+单步执行,程序在执行时崩溃 mov dword ptr [rax],ecx …当程序基本上尝试取消引用%rdx的原始值时(从函数第一次调用时开始),该值现在位于
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
导致调用的代码是_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;
}
...
}
...
}
。。。
对于(Counter=0;Counter这看起来像是VS2010中的。报告链接到Microsoft Connect。还有错误。SP1中修复了大量优化ugs,因此我可能没有链接正确的优化ugs(发现另外三个只是筛选链接)。我在此处向MS发布了错误报告:
再次感谢大家的帮助
else if (strchr((char*)Other_Uchar_Table_Of_Enum_Values, myOther32BitType.8BitField)) continue;
这看起来大错特错。与其求助于完全不必要的强制转换,不如使用std::find
事实上,你的整个代码看起来到处都是C风格的不安全代码。内存管理对象在哪里?听起来像是代码中其他地方的内存损坏。提高编译器的警告级别,留意数据截断警告。还要留意那些假定它知道基本类型大小的代码。是的,这就是w我目前正在做的事情。不幸的是,这段代码有太多的缺点,这让人很痛苦。:PI可能在这里不存在,但我有一个隐秘的怀疑,在32位编译中,联合体的所有_位成员和位字段的大小都将是32位,而在64位编译中,所有_位都可能是64位宽。您可能想使用在这两种情况下都会出现一些问题……这可能真的是一个代码生成错误。我很想看到函数的完整反汇编。我想我要做的是,被调用方几乎希望调用方指定一个out参数来接收返回值。(在amd64上的MS land中,前两个参数在rcx
和rdx
中传递。我假设函数开始时的rcx
就是这里的此
指针。)似乎被调用者期望这样做,但调用者没有这样做。标头和实现之间或者编译单元之间可能存在某种不匹配吗?:/我希望你是对的,但在安装SP1后,问题仍然出现。很可能是我们方面的问题,而不是MS方面的问题,但它是值得的一个快照。无论如何谢谢!这是非托管代码。请注意,这不是我的代码。这是我现在负责转换的五年积累的代码。只需在头文件中向is_Inst的声明添加另一个参数(例如,“nid is_Inst(int Dummy=0);”)就可以作为一种解决方法