Delphi CopyMemory против C ++ memcpy - PullRequest
       32

Delphi CopyMemory против C ++ memcpy

8 голосов
/ 29 декабря 2011

ОК. Поэтому у меня никогда не возникает простого вопроса.

У меня есть пользовательская библиотека (которую я не пишу), написанная на C ++.Эта библиотека выполняет некоторые сетевые коммуникации, и я просто передаю ей некоторые данные в виде байтового массива и извлекаю из него байтовый массив с другой стороны.Библиотека обрабатывает все сетевые вещи для меня отправка / получение данных на / с клиента / сервера.

Так, например, я могу написать клиент и сервер.С клиента я создаю байтовый массив, библиотека берет байтовый массив и отправляет его на сервер.Сервер, который я написал, использует ту же библиотеку для обратного, то есть обрабатывает весь прием трафика и в конечном итоге передает обратно байтовый массив.

Библиотека определяет байтовый массив как часть структуры следующим образом... (Я загружаю библиотеку статически в Delphi, не думаю, что это будет иметь значение, но я использую FastMM4 - это повлияет на модель разделения памяти между приложением и dll? Насколько я знаюиспользование FastMM должно быть в порядке, также пробовал ShareMem безрезультатно)

struct content {
  void *data;
  int size;
}

В любом случае, с моего клиента я пытаюсь отправить «Hello» ... общепринятым считается, что данные байтового массива копируютсяв эту структуру, используя 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 ++ ... Но замена клиента C ++ на клиент, написанный на Delphi, не работает.Я заменил memcpy на CopyMemory, который, как мне показалось, сделал то же самое, но каким-то образом мой байтовый массив изменился к тому времени, когда он достигает сервера C ++ ... Мой клиент Delphi делает следующее ...

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

Таким образом, данные от клиента Delphi выглядят корректно, но данные, полученные на сервере, неверны ... Каким-то образом "Hello" ('72 101 108 108 111 ') становится

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

Я подозреваю, что ячто-то не так с CopyMemory ...?Или я неправильно разделил память между exe и dll?Как узнать, какую модель памяти использует сетевая библиотека C ++?Или я просто скопировал этот байтовый массив неправильно?Любая помощь высоко ценится ...

1 Ответ

13 голосов
/ 29 декабря 2011
CopyMemory(lContentPointer, @ByteArray, 5);

Ошибка в том, что ByteArray, по сути, является указателем на первый элемент массива. Таким образом, вы передаете адрес указателя на первый элемент массива. Другими словами, у вас есть дополнительный, ложный уровень косвенности. Вам нужно

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

или

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

Что касается CopyMemory против memcpy, первый - это функция Win32 API, а второй - функция стандартной библиотеки Си. Эти две функции выполняют идентичные задачи и являются взаимозаменяемыми.

...