2012-12-05 97 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面。