当然,分配和释放同一个指针是明确定义的......
void *p1 = malloc(42);
assert(p1);
...
free(p1);
... 并通过 intptr_t/uintptr_t
转换创建一个 可比较 指针(如“比较等于”C11 7.20.1.4 中)当这些整数类型存在时,尽管不存在一定是相同的位模式。可以说 p2
和 p3
具有相同的值,但可能有不同的表示。
void *p2 = malloc(42);
assert(p2);
uintptr_t u2 = (uintptr_t) p2;
...
void *p3 = (void *) u2;
// Specified to evaluate true C11 7.20.1.4
if (p2 == p3) ...
// Maybe true, maybe false
if (memcmp(&p2, &p3, sizeof p2) == 0) ...
// Note - early version of post had this errant code
// if (memset(&p2, &p3, sizeof p2) == 0) ...
现在通过一个可比较指针到free()
。
The
free
function causes the space pointed to byptr
to be deallocated, ... if the argument does not match a pointer earlier returned by a memory management function ... behavior is undefined. C11dr §7.22.3.3 3
void *p4 = malloc(42);
assert(p4);
uintptr_t u4 = (uintptr_t) p4;
...
void *p5 = (void *) u4;
...
free(p5); // UB or not UB?
所以标题问题似乎完成了:
关于 free()
,“可比”是否足以“匹配”?
我怀疑 free(p5)
是 undefined behavior (UB),但不确定。没有特定的应用程序 - 只是想了解 C 的角落,不要着急。
最佳答案
引用是 N1570 ,2011 年 ISO C 标准 (C11) 的最新公开草案。
void *p4 = malloc(42);
assert(p4);
uintptr_t u4 = (uintptr_t) p4;
...
void *p5 = (void *) u4;
...
free(p5); // UB or not UB?
uintptr_t
的定义保证指针值p4
和p5
比较相等;更简洁地说,p4 == p5
。从 6.5.9p6 中指针的 ==
定义,我们知道 p4
和 p5
指向同一个对象(因为我们已经已经确定 p3
的值不是空指针)。
这并不能保证它们具有相同的表示形式。该标准很少提及指针的表示形式(除了它们具有表示形式),因此 p4
和 p5
完全有可能具有不同的表示形式。该标准在 6.2.6.1p4 中明确允许这样做:
Two values (other than NaNs) with the same object representation compare equal, but values that compare equal may have different object representations.
(这实际上可能会或可能不会,具体取决于实现情况。)
现在的问题是,到底传递给free
的是什么?
函数调用在 6.5.2.2 中描述。第 4 段说:
In preparing for the call to a function, the arguments are evaluated, and each parameter is assigned the value of the corresponding argument.
(强调已添加。)
所以 free()
看到的不是 p5
的对象表示(这可能与 p4
的对象表示不同),而是p5
的值,保证与p4
的值相同。传递该值的机制可能涉及制作对象表示的副本,但所有标准都说该值已传递,并且 free
必须处理相同对象的任何不同表示以同样的方式值(value)。
关于c - `free(a_comparable_pointer)` 是定义明确还是 UB?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39582559/