简体   繁体   English

使用`memcpy()`为指针分配地址

[英]Using `memcpy()` to assign a pointer an address

Is

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

the same as 与...相同

ptr = &value;

..... .....

I've never seen memcpy() used to do this before. 我以前从未见过memcpy()用于执行此操作。 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 . 编辑:似乎重要的是要注意ptrvoid * ptr value is double value . valuedouble value


Edit2: For those who are interested in following this problem down its rabbit hole with me read along. Edit2:对于那些有兴趣跟着这个问题进行研究的人,请与我一起阅读。 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. 静态分析担心目标缓冲区ptr可能没有足够的空间来保存sizeof(char *)sizeof(char *)的信息。
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). 我没有去解决它给我带来的问题,而是试图确切地了解此memcpy()所做的事情(感谢您的帮助)。 Once I understood what was happening, I had to understand why the size of memory given to memcpy() was sizeof(char *) ; 一旦了解了所发生的事情,就必须理解为什么赋予memcpy()的内存大小为sizeof(char *) the function this memcpy() is in is called one time, and that one time it looks like this: memcpy()所在的函数被调用一次,并且该调用看起来像这样:

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! 这意味着该函数内以及memcpy()调用中ptr的实际值是另一个指针的地址!

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. 对我来说,以前的开发人员会memcpy()一个sizeof(char *)的数据量真是让我感到很奇怪,因为该系统是在32位和64位计算机上编译的。 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). 但是,由于他将指向指针( &ptr )的地址作为ptr传递到函数中,因此他不仅避免了根据系统体系结构从4字节指针转换为8字节指针的过程,而且还完全按照他的意思进行了操作(我认为)。 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 . 最后,在64位系统上,所有double value都将被复制到ptr指向的地址中,该地址实际上是指向另一个指针( &ptr )的地址,而在32位计算机上,一半的值将被复制。的位置ptr这实在是&ptr Now I just need to figure out what that double value really represents, and why he would be ok bisecting it. 现在,我只需要弄清楚那个double value真正代表什么,以及他为什么可以将其对等。

If that didn't make sense, I'll try again, but it feels a like he was Inception-ing the pointer. 如果那没有道理,我会再试一次,但是感觉就像他在盗版一样。 =) =)

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. 如果可以使用=代替,最好避免使用memcpy()

Among other things, if the types are incorrect, then = will generate the proper diagnostics, while memcpy() will happily crash your program or worse. 除其他事项外,如果类型不正确,则=将生成正确的诊断信息,而memcpy()将使您的程序崩溃甚至更糟。

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 . 使用sizeof(char *)是错误的,因为如果要复制double ,则应该为sizeof(double)

Theoretically, you could be doing something more esoteric, but I'll ignore that possibility. 从理论上讲,您可能会做一些更深奥的事情,但我会忽略这种可能性。

This changes the address that the pointer ptr points to: 这将更改指针ptr指向的地址

ptr = &value;

This changes the data at the address that the pointer ptr points to: 这将更改指针ptr指向的地址处的数据

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

In the second case, ptr still points to the same address as before the call. 在第二种情况下, ptr仍指向与调用前相同的地址。 So in no way are they the same. 所以他们绝对不是一样的。

That memcpy is like memcpy就像

*ptr = value;

So ptr has to point to a char * (assuming value is, according to the sizeof ). 因此, ptr必须指向一个char * (假设value是根据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 . 假设ptrchar ** (或者您将其更改为采用ptr的地址: &ptr )并正确初始化,那么我在这里没有发现实际问题。 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). 哦,而且:该代码更难以阅读/手动验证/理解,IOW:难以维护(如注释和我自己的编辑所示)。 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. 注意:无论谁写这样的代码,很可能在其他地方写更多的废话。

The assignment notation is much more concise and readable then using memcpy and allows compiler optimization. 与使用memcpy相比,赋值表示法更为简洁和易读,并允许编译器优化。 The = means an assignment, while memcpy just copies memory. =表示分配,而memcpy仅复制内存。
You should stick with the = assignment 您应该坚持=赋值

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM