Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Delphi CopyMemory vs C++ memcpy

OK - So I never seem to have a simple question.

I have a custom library (which is not written by me) written in C++. This library does some network comms and I just pass some data to it as a byte array and retrieve a byte array from it on the other side. The library handles all the network stuff for me the sending/receiving of data to/from client/server.

So for example, I can write a client and a server. From the client I produce a byte array, the library takes the byte array and sends it to a server. The server I've written uses the same library to do the reverse, ie handle all the receiving of traffic and eventually passes back a byte array.

The library defines the byte array as part of a struct as follows... (I'm loading the library statically in Delphi, don't think that'll make a difference, but I am using FastMM4 - is this going to affect the memory sharing model between app and dll? Far as I'm aware using FastMM should be OK, have also tried ShareMem to no avail)

struct content {
  void *data;
  int size;
}

Anyway, from my client I am attempting to send "Hello"... the accepted wisdom is that the byte array data is copied into this struct by using memcpy like so...

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

On my server I reply with "World". So the server replies as follows...

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

From a C++ client communicating with a C++ Server I receive this data on the server...

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

So after that essay, I think the C++ server code is correct because I can communicate correctly if I write a client in C++... But replacing the C++ client with a client written in Delphi doesn't work. I've replaced memcpy with CopyMemory, which I thought did the same thing but somehow my byte array is different by the time it reaches the C++ server... My Delphi client does the following...

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

So the data from the Delphi client appears correct, but the data received on the server is incorrect... Somehow "Hello" ('72 101 108 108 111') becomes

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

I suspect I am doing something wrong with CopyMemory...? Or have I got the memory sharing wrong between the exe and the dll? How do I know what kind of memory model the C++ networking library uses? Or have I just copied that byte array incorrectly? Any help much appreciated...

like image 499
0909EM Avatar asked Dec 29 '11 18:12

0909EM


People also ask

What can I use instead of memcpy?

memmove() is similar to memcpy() as it also copies data from a source to destination.

When should memcpy be used?

The function memcpy() is used to copy a memory block from one location to another. One is source and another is destination pointed by the pointer.

Is memcpy fast?

memcpy is likely to be the fastest way you can copy bytes around in memory. If you need something faster - try figuring out a way of not copying things around, e.g. swap pointers only, not the data itself.

Can we use memcpy in C++?

The memcpy() function in C++ copies specified bytes of data from the source to the destination. It is defined in the cstring header file.


1 Answers

CopyMemory(lContentPointer, @ByteArray, 5);

The error is that ByteArray is, effectively, a pointer to the first element of the array. You are thus passing the address of the pointer to the first element of the array. In other words you have an extra, spurious, level of indirection. You need

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

or

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

As for CopyMemory vs memcpy, the former is a Win32 API function and the latter is a C standard library function. The two functions perform identical tasks and are interchangeable.

like image 197
David Heffernan Avatar answered Sep 19 '22 19:09

David Heffernan