Chr*_*oph 14 c free pointers standards-compliance compiler-optimization
有人声称
编译器可以自由地将指针变量重用于其他目的之后
realloc被释放,所以你不能保证它具有与之前相同的价值
即
void *p = malloc(42);
uintptr_t address = (uintptr_t)p;
free(p);
// [...] stuff unrelated to p or address
assert((uintptr_t)p == address);
Run Code Online (Sandbox Code Playgroud)
可能会失败.
C11附件J.2读
使用指向通过调用free或realloc函数释放的空间的指针的值(7.22.3)[ 未定义 ]
但附件当然不是规范性的.
附件L.3(规范性的,但可选的)告诉我们,如果
使用指向通过调用free或realloc函数解除分配的空间的指针的值(7.22.3).
结果被允许是关键的未定义行为.
这证实了这一说法,但我希望从标准本身而不是附件中看到适当的引用.
Pas*_*uoq 16
当一个对象到达其生命周期的末尾时,所有指向它的指针都变得不确定.这适用于块范围变量和malloced内存.适用的条款在C11,6.2.4:2中.
对象的生命周期是程序执行的一部分,在此期间保证为其保留存储.存在一个对象,具有一个常量地址,并在其整个生命周期内保留其最后存储的值.如果在其生命周期之外引用对象,则行为未定义.当指针指向(或刚刚过去)的对象到达其生命周期的末尾时,指针的值变得不确定.
使用不确定的内存来处理任何事情,包括明显无害的比较或算术,都是未定义的行为(在C90中;后来的标准使事情变得非常复杂,但编译器继续将不确定内存的使用视为未定义的行为).
作为一个例子,下面的程序打印怎么样,p并且q是不同的和相同的?与各种编译器执行的结果显示在这里.
#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);
}
}
Run Code Online (Sandbox Code Playgroud)