2012-12-05 96 views
2

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

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指向的内存中。所以在第一行中,一个值被移入寄存器rcx。这我已经验证指向pCM。然后将rcx + 0BDEh指向的值复制到rcx中。并调用memcpy。这工作。

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

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

任何帮助,将不胜感激。

+0

您是否尝试过使用较新版本的VC++?对于我们所知道的这是编译器中的一个代码问题,此后已经修复。 : - ] – ildjarn

+0

这些调试版本或优化?也许你可以显示任何'pCM'指向的结构? –

+0

另外,'pCM-> pSecAccInfo-> spUserID'中有两个重定向似乎很奇怪,但汇编代码似乎只执行一个(在每个示例中)。例如,在你的第一个汇编代码片段中,第一次加载到'rcx'大概是从本地堆栈变量加载'pCM'到寄存器,然后'rcx'的下一个加载将加载'pSecAccInfo' - 但是'rcx'应该有在调用memcpy()之前,在'rcx'中调用'spUserID'。有可能通过优化,第一个负载实际上是'pSecAccInfo'(但你说你确认它是'pCM')。 –

回答

1

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

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

...在你的结构定义,以获得C++方面具有相同的填充行为作为项目的C面。