Are there any use cases relying on integer representation of two allocations being different in C?

荒凉一梦 提交于 2019-12-08 15:19:12

问题


For example, consider the following C code snippet:

void *p = malloc(1);
void *q = malloc(1);

bool question = (uintptr_t) p == (uintptr_t) q;

I expect everyone expects question be always false. (Surprisingly, the C11 standard does not require it, though. The only restriction on uintptr_t is e.g. ((void *) ((uintptr_t) p)) == p. See 7.20.1.4 of the C11 standard for details.)

My question is: is there any realistic use case that actually relies on the guarantee that question be false, or more generally, the integer representations of two allocations be different?


回答1:


The question is flawed. First, consider this code (where we suppose that malloc does not return null):

void *p = malloc(1);
void *q = malloc(1);

bool question = (uintptr_t) p == (uintptr_t) q;

Per the C 2011 standard’s specification of uintptr_t, if we do:

void *p1 = (void *) (uintptr_t) p;
void *q1 = (void *) (uintptr_t) q;

Then p1 must compare equal to p, and q1 must compare equal to q. And, per the standard’s specification of the == operator, p1 and q1 must not compare equal to each other, since they are, respectively, equal to p and to q, and hence are pointers to different objects.

Because (void *) (uintptr_t) p and (void *) (uintptr_t) q produce different values, (uintptr_t) p and (uintptr_t) q must be different values. (This is because the conversion to void * is a mathematical function within the C model. Every time it is given a specific value, within the rules of C, it produces a result that is effectively the same, within the rules of C.) Therefore (uintptr_t) p is not equal to (uintptr_t) q.

Now consider this code, where we change void * to char *:

char *p = malloc(1);
char *q = malloc(1);

bool question = (uintptr_t) p == (uintptr_t) q;

The specification of uintptr_t is silent about conversions from char *. Obviously, these pointers to char * can be converted to void *. However, I do not see that the standard requires that a conversion from char * to uintptr_t must implicitly insert a conversion to void * or act as if it did. So I suppose this is technically undefined by the standard. But I doubt you will find any C implementation in which this differs from the void * version, except one constructed specifically to violate this.

Nonetheless, effectively every programmer that uses uintptr_t expects the result to fully identify the original pointer (it contains all the information to convert back to the original pointer), and hence they expect the uintptr_t result to differ from that of all different pointers.

As for one specific example, the Accelerate framework in macOS expects the result of converting different pointers to uintptr_t to produce different results, and I am sure many other parts of macOS do too.



来源:https://stackoverflow.com/questions/47481834/are-there-any-use-cases-relying-on-integer-representation-of-two-allocations-bei

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!