2

我在尝试将 32 位产品转换为 64 位产品时遇到问题。我使用的是 Visual Studio 2008,代码是 C 和 C++。我希望任何人查看以下两行代码,一行来自 C 源文件,另一行来自 C++ 源文件。这两个文件都包含在 DLL 中。我还包括对两行代码的反汇编。

ewxlcom.c

memcpy(pCM->pSecAccInfo->spUserID,userSecurityInfo.spUserID,
     sizeof(UserID));
000000000EF33BB9  mov         r8d,80h 
000000000EF33BBF  mov         rdx,qword ptr [rsp+828h] 
000000000EF33BC7  mov         rcx,qword ptr [rsp+1F8h] 
000000000EF33BCF  mov         rcx,qword ptr [rcx+0BDEh] 
000000000EF33BD6  call        memcpy (0EF40352h) 

tcputil.cpp

memcpy(serv_temp+INIT_MSG_USERID_OFFSET, pCM->pSecAccInfo->spUserID, INIT_MSG_USERID_LEN);
000000000EF3B8E6  lea         rcx,[rsp+67h] 
000000000EF3B8EB  mov         r8d,80h 
000000000EF3B8F1  mov         rdx,qword ptr [rsp+3B0h] 
000000000EF3B8F9  mov         rdx,qword ptr [rdx+0CBEh] 
000000000EF3B900  call        memcpy (0EF40352h) 

如您所见,第一行将一些字节复制到 指向的内存中pCM->pSecAccInfo->spUserID。第二行将这些相同的字节复制到内存中的另一个位置。ASM 将memcpy字节从寄存器指向的内存复制到寄存器rdx指向的内存rcx。因此,在第一行中,一个值被移入了 register rcx。这一点我已经验证指向pCM。然后将 指向的值rcx + 0BDEh复制到rcx. 并且memcpy被称为。这行得通。

但稍后在第二行将一个值加载到 register rdx。我已经验证这也指向与pCM第一行相同的内容。pCM然后它加载驻留在从( rdx)偏移的内存中的指针0CBEh。该内存全为零,因此memcpy崩溃。

问题是为什么编译器会为同一个源变量生成不同的代码。我认为这是一个对齐问题。这是C文件和C++文件之间的区别吗?VS 是否对 C 和 C++ 使用相同的编译器?还有什么我应该看的吗?

任何帮助,将不胜感激。

4

1 回答 1

1

如果您要链接 C 和 C++ 代码,您可能需要注意结构中的不同填充特性。也许创建一个临时函数来打印结构的每个成员的偏移量,并将相同的代码从 C 源文件(您编写它的位置)复制到 C++ 源文件。函数的两个副本可以保持不变,因为 C++ 的副本会被破坏,但我会在每个副本的顶部添加一个 printf() 来说明它是哪个版本。然后在崩溃前从某个地方调用每个,以便您可以比较偏移量。如果它们不同,则需要查看编译器标志来解决该问题。或者...也许您需要添加这样的行...

#ifdef __cplusplus
extern "C" {
#endif
 .
 .    ...your struct definitions & variables go here...
 .
#ifdef __cplusplus
}
#endif

...围绕您的结构定义,以使 C++ 端具有与项目的 C 端相同的填充行为。

于 2012-12-05T00:55:10.280 回答