Using `memcpy()` to assign a pointer an address

11k views Asked by At

Is

memcpy( ptr, &value, sizeof(char *) );

the same as

ptr = &value;

.....

I've never seen memcpy() used to do this before. It seems like I should respond to the developer of this code with the phrase "Well, you're not wrong." It seems like a bit wordier than it needs to be.

Edit: It seems important to note that ptr is void * ptr. value is double value.


Edit2: For those who are interested in following this problem down its rabbit hole with me read along. This bit of code was flagged by static analysis as a potential buffer overflow. The static analysis was worried that the destination buffer ptr might not have enough space to hold a sizeof(char *) worth of information.
Rather than deal with the problem it gave me I tried to understand exactly what this memcpy() did (thank you for helping me with that). Once I understood what was happening, I had to understand why the size of memory given to memcpy() was sizeof(char *); the function this memcpy() is in is called one time, and that one time it looks like this:

SdmJniGetPointer(blah, blah, &ptr)

Meaning that the actual value of ptr within this function, and in the memcpy() call, is the address of another pointer!

It was bizzare to me that the previous developer would memcpy() a sizeof(char *) amount of data because this system is compiled on 32 and 64 bit machines. However, because he passes in the address to a pointer (&ptr) into the function as ptr, he not only circumvents this shifting from 4-byte pointers to 8-byte pointers depending on the system architecture but wields it exactly as he meant too (I think). In the end, on a 64-bit system, all of the double value is copied into the address pointed to by ptr which is really an address to a different pointer (&ptr), and on 32-bit machines, half of it is copied to the location ptr which is really &ptr. Now I just need to figure out what that double value really represents, and why he would be ok bisecting it.

If that didn't make sense, I'll try again, but it feels a like he was Inception-ing the pointer. =)

4

There are 4 answers

5
Jonathan Potter On BEST ANSWER

This changes the address that the pointer ptr points to:

ptr = &value;

This changes the data at the address that the pointer ptr points to:

memcpy(ptr, &value, sizeof(char*));

In the second case, ptr still points to the same address as before the call. So in no way are they the same.

5
Dietrich Epp On

No, it is absolutely different. Let's add some types:

char *addr;
char **ptr = &addr;
char *value = "Hello";

memcpy(ptr, &value, sizeof(char *));
// Equivalent to...
*ptr = value;

Better to avoid memcpy() if it is possible to use = instead.

Among other things, if the types are incorrect, then = will generate the proper diagnostics, while memcpy() will happily crash your program or worse.

Given the types,

double value, value2;
void *ptr = &value2;

// This copies `value` into `value2`.
memcpy(ptr, &value, sizeof(double));

Using sizeof(char *) is wrong, because it should be sizeof(double) if you are copying a double.

Theoretically, you could be doing something more esoteric, but I'll ignore that possibility.

5
too honest for this site On

That memcpy is like

*ptr = value;

So ptr has to point to a char * (assuming value is, according to the sizeof).

Assuming ptr is char ** (or you change that to take the address of ptr: &ptr) and properly initialized, I see no actual problem here. However, this code inhibits type checking by the compiler and is likely slower than a simple assignment.

It also might exhibit problems with aliasing if source and destination have different typs (as the edit implies). It also will likely prohibit optimizations.

Oh, and: that code is more difficult to read/manually verify/understand, IOW: to maintain (as the comments and my own edits show). Maybe the developer was after job safety by obfuscation?

Edit:

After your edit adding type information: That code is even worse. It does not even use the same types. My advise: kick the author where it really hurts and then rewrite the code very carefully. Note: whoever write such code, very likely writes more crap elsewhere.

0
Brockr22 On

The assignment notation is much more concise and readable then using memcpy and allows compiler optimization. The = means an assignment, while memcpy just copies memory.
You should stick with the = assignment