据称已经声称
在
realloc被释放之后,编译器可以自由地将指针变量重用于其他目的,所以你不能保证它具有与它相同的值。前
即
void *p = malloc(42);
uintptr_t address = (uintptr_t)p;
free(p);
// [...] stuff unrelated to p or address
assert((uintptr_t)p == address);
可能会失败。
C11附件J.2读取
指向通过调用free或者释放释放的空间的指针的值 使用realloc函数(7.22.3)[未定义]
但附件当然不是规范性的。
附件L.3(规范性的,但可选的)告诉我们,如果
指向通过调用free或realloc释放的空间的指针的值 使用函数(7.22.3)。
结果被允许是关键的未定义行为。
这确认了索赔,但我希望从标准本身而不是附件中看到适当的引用。
答案 0 :(得分:16)
当一个对象到达其生命周期的末尾时,指向它的所有指针都变为 indeterminate 。这适用于块范围变量和malloced内存。适用的条款在C11,6.2.4:2中。
对象的生命周期是程序执行的一部分,在此期间保证为其保留存储。存在一个对象,具有一个常量地址,并在其整个生命周期内保留其最后存储的值。如果在其生命周期之外引用对象,则行为未定义。当指针指向(或刚刚过去)的对象到达其生命周期的末尾时,指针的值变得不确定。
对任何事物使用不确定的内存,包括显然无害的比较或算术,都是未定义的行为(在C90中;后来的标准使事情变得非常复杂,但编译器继续将不确定内存的使用视为未定义的行为)。
例如,p
和q
的以下程序打印如何不同且相同?使用各种编译器执行的结果显示为here。
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
int main(int argc, char *argv[]) {
char *p, *q;
uintptr_t pv, qv;
{
char a = 3;
p = &a;
pv = (uintptr_t)p;
}
{
char b = 4;
q = &b;
qv = (uintptr_t)q;
}
printf("Roses are red,\nViolets are blue,\n");
if (p == q)
printf ("This poem is lame,\nIt doesn't even rhyme.\n");
else {
printf("%p is different from %p\n", (void*)p, (void*)q);
printf("%"PRIxPTR" is not the same as %"PRIxPTR"\n", pv, qv);
}
}