2011-12-29 118 views
8

好的 - 所以我似乎沒有一個簡單的問題。Delphi CopyMemory vs C++ memcpy

我有一個用C++編寫的自定義庫(不是我寫的)。這個庫做一些網絡通信,我只是將一些數據作爲一個字節數組傳遞給它,並從另一端檢索一個字節數組。該庫處理所有的網絡資料,用於向客戶端/服務器發送/接收數據。

因此,例如,我可以編寫客戶端和服務器。從客戶端產生一個字節數組,該庫獲取字節數組並將其發送到服務器。我寫的服務器使用相同的庫來完成相反的操作,即處理所有的流量接收並最終傳回一個字節數組。

該庫將字節數組定義爲結構的一部分,如下所示...(我在Delphi中靜態加載庫,不認爲這會有所作爲,但我使用FastMM4--這是會影響到應用程序和DLL之間的內存共享模式嗎?據我知道使用FastMM應該OK,也試圖ShareMem無濟於事)

struct content { 
    void *data; 
    int size; 
} 

無論如何,從我的客戶,我試圖發送「你好「......公認的看法是,通過使用memcpy將字節數組數據複製到此結構中,像這樣...

char *data = "Hello"; 
memcpy((void *)content.data(), data, strlen(data)); // last parameter is length, ie 5 
// network.sendrequest(content); 
// where content.data() returns the aforementioned pointer 

在我的服務器上,我回復了「World」。因此,服務器回覆如下...

char *data = "World"; 
memcpy((void *)content.data(), data, strlen(data)); // last parameter is length, ie 5 
// network.sendreply(content); 

從C++客戶端與C++服務器我收到服務器上的此數據通信...

0x0035fdf6 "Hello" (or in Bytes... 72, 101, 108, 108, 111) 

這樣的文章後,我覺得C++服務器代碼是正確的,因爲如果我用C++編寫客戶端,我可以正確通信......但用用Delphi編寫的客戶端代替C++客戶端不起作用。我換成CopyMemory的,而且我認爲他做了同樣的事情,但不知何故,我的字節數組是由它到達C++服務器的時間不同的memcpy ...我的德爾福的客戶將執行以下操作...

// lDataPointer is a retrieved reference to the 
// pointer (void *data; see above) defined in the 
// C++ library. It appears to be a valid pointer at runtime... 
lContentPointer := content.data(); // from DLL 
// Where ByteArray is populated with byte data of "Hello" 
CopyMemory(lContentPointer, @ByteArray, 5); // Copy from Exe to DLL 
// network.sendrequest(lContentPointer); 

// I have printed the byte array before the CopyMemory to check 
// its contents before sending, which is '72 101 108 108 111' 

所以從德爾福客戶端的數據似乎是正確的,但在服務器上接收到的數據是不正確......不知怎的,「你好」(1972 101 108 108 111' )成爲

0x003efd96 "h,H" (or in Bytes 104, 19, 44, 2, 72) 

我懷疑我在做什麼毛病CopyMemory的......?或者我有exe和dll之間的內存共享錯誤?我如何知道C++網絡庫使用什麼樣的內存模型?或者我錯誤地複製了該字節數組?任何幫助非常感謝...

+1

我想你可能會誤解一些關於DLL的東西。 EXE和DLL之間沒有「內存共享模型」 - 它們運行在相同的地址空間中。您可以來回傳遞指針,EXE或DLL可以無限制地讀/寫它們。但是,特定的DLL可能會要求您根據其特定接口複製參數。在你的情況下,誰分配的空間'content.data'?您是否可能將數據複製到由未初始化的指針確定的隨機空間中? – 2011-12-29 18:31:51

+1

嘗試CopyMemory(lContentPointer,@ByteArray [0],5); – ComputerSaysNo 2011-12-29 18:36:06

+0

我認爲你忘了在C字符串中複製*最後的零字節*。例如。 memcpy((void *)content.data(),data,strlen(data)+1); C字符串約定是字符串應該以零字節結尾。帕斯卡(也許德爾福,我不知道)可能有不同的約定(例如,用一個字給出它們的長度來開始字符串)。 我無法回答你有關'CopyMemory'的問題。 – 2011-12-29 18:36:59

回答

12
CopyMemory(lContentPointer, @ByteArray, 5); 

的錯誤是ByteArray是,有效地,一個指針數組的第一個元素。因此,您將指針的地址傳遞給數組的第一個元素。換句話說,你有一個額外的,虛假的,間接的層次。您需要

CopyMemory(lContentPointer, @ByteArray[0], 5); 

CopyMemory(lContentPointer, Pointer(ByteArray), 5); 

至於CopyMemory VS memcpy,前者是一個Win32 API函數,而後者是一個C標準庫函數。這兩個功能執行相同的任務並且可以互換。

+0

謝謝大衛......認爲這是兩週內你回答我的帖子兩次... – 0909EM 2011-12-29 19:04:37

+0

@ 0909EM是的,他是這裏的活躍Delphi專家,+1 – 2011-12-29 21:21:22

+0

@Seth你的許多意思之一;-) – 2011-12-29 21:32:28