2011-12-29 11 views
8

OK - Więc nigdy nie mam prostego pytania.Delphi CopyMemory vs C++ memcpy

Mam niestandardową bibliotekę (która nie jest napisana przeze mnie) napisaną w C++. Ta biblioteka wykonuje pewne komunikaty sieciowe i właśnie przekazuję do niej niektóre dane jako tablicę bajtów i pobiera z niej tablicę bajtów po drugiej stronie. Biblioteka obsługuje wszystkie zasoby sieciowe dla mnie, wysyłanie/odbieranie danych do/z klienta/serwera.

Na przykład mogę napisać klienta i serwer. Z klienta generuję tablicę bajtów, biblioteka pobiera tablicę bajtów i wysyła ją do serwera. Napisany przeze mnie serwer używa tej samej biblioteki, aby wykonać odwrotność, tj. Obsłużyć cały odbiór ruchu i ostatecznie przekazuje z powrotem tablicę bajtów.

Biblioteka definiuje tablicę bajtów jako część struktury w następujący sposób ... (ładuję bibliotekę statycznie w Delphi, nie sądzę, że to coś zmieni, ale używam FastMM4 - czy to wpłynie modelu udostępniania aplikacji i pamięci między dll? ile jestem świadomy używając FastMM powinno być OK, też próbował ShareMem bezskutecznie)

struct content { 
    void *data; 
    int size; 
} 

w każdym razie, od mojego klienta Jestem próbuje wysłać " Cześć "... przyjęta mądrość polega na tym, że dane tablicy bajtów są kopiowane do tej struktury za pomocą memcpy, tak jak ...

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 

Na moim serwerze odpowiadam słowem "Świat". Więc serwer odpowiada następująco ...

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

Z C++ klient komunikuje się z serwerem C++ I otrzymać te dane na serwerze ...

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

więc po tym eseju, myślę, że Kod serwera C++ jest poprawny, ponieważ mogę poprawnie komunikować się, jeśli piszę klienta w C++ ... Ale zastąpienie klienta C++ klientem napisanym w Delphi nie działa. Mam zastąpiony memcpy z CopyMemory, co uważałem, że zrobił to samo, ale jakoś moja tablica bajtów jest inna od tej chwili ich serwer C++ Delphi ... Mój klient wykonuje następujące ...

// 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' 

Tak dane z klientem Delphi wydaje się poprawne, ale dane otrzymane na serwerze jest nieprawidłowy ... jakoś „Hello” ('72 101 108 108 111') staje

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

podejrzewam robię coś złego CopyMemory ...? Czy mam błąd dzielenia pamięci między exe i dll? Skąd mam wiedzieć, jakiego modelu pamięci używa biblioteka sieciowa C++? A może właśnie skopiowałem niepoprawnie tablicę bajtów? Każda pomoc mile widziane ...

+1

Myślę, że możesz być nieporozumieniem co do bibliotek DLL. Nie ma "modelu współużytkowania pamięci" między EXE i DLL - działają one w tej samej przestrzeni adresowej. Możesz przekazywać wskaźniki w jedną i drugą stronę, a EXE lub DLL mogą je czytać/zapisywać bez ograniczeń. Jednak konkretna biblioteka DLL może wymagać kopiowania parametrów w zależności od konkretnego interfejsu. W twoim przypadku, kto przydziela miejsce dla 'content.data'? Czy możliwe jest skopiowanie danych do losowej przestrzeni określonej przez niezainicjowany wskaźnik? –

+1

spróbuj CopyMemory (lContentPointer, @ByteArray [0], 5); – ComputerSaysNo

+0

Myślę, że zapomniałeś skopiować * ostatni bajt zero * w ciągach C. Na przykład. memcpy ((void *) content.data(), dane, strlen (dane) +1); Konwencja łańcuchów C polega na tym, że łańcuchy powinny być zakończone bajtem zerowym. Pascal (i być może Delphi, nie wiem) może mieć inną konwencję (np. Ciągi początkowe z wyrazem podającym ich długość). Nie mogę odpowiedzieć na twoje pytanie związane z 'CopyMemory'. –

Odpowiedz

12
CopyMemory(lContentPointer, @ByteArray, 5); 

Błąd jest ByteArray jest skutecznie, wskaźnik do pierwszego elementu tablicy. W ten sposób przekazujesz adres wskaźnika do pierwszego elementu tablicy. Innymi słowy, masz dodatkowy, fałszywy poziom pośredni.Trzeba

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

lub

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

chodzi CopyMemory vs memcpy, były to funkcja Win32 API a druga jest funkcją średnia biblioteka C. Obie funkcje wykonują identyczne zadania i są wymienne.

+0

Dzięki David ... Pomyśl, że to dwa razy w ciągu dwóch tygodni odpowiedziałeś na moje posty ... – 0909EM

+0

@ 0909EM tak, jest aktywnym ekspertem Delphi tutaj, +1 –

+0

@Seth Jednym z wielu, które masz na myśli ;-) –