当前位置: 首页 > 知识库问答 >
问题:

是否允许编译器回收释放的指针变量?

桑坚成
2023-03-14

IE

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内容如下

共有1个答案

陶英纵
2023-03-14

当一个对象达到其生命周期的末尾时,指向它的所有指针都变得不确定。这同样适用于块作用域变量和配置不当的内存。适用的条款是C116.2.4:2。

对象的生存期是程序执行过程中保证为其保留存储空间的部分。对象存在,具有恒定的地址,并在其整个生存期内保留其最后存储的值。如果对象在其生命周期之外被引用,则该行为是未定义的。当指针所指向的对象(或刚刚过去的对象)达到其生存期结束时,指针的值将变得不确定。

将不确定内存用于任何事情,包括显然无害的比较或算术,都是未定义的行为(在C90中;后来的标准使问题变得非常复杂,但编译器继续将不确定内存的使用视为未定义的行为)。

#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);
  }
}
 类似资料:
  • 本文向大家介绍什么是指针的释放? 相关面试题,主要包含被问及什么是指针的释放? 时的应答技巧和注意事项,需要的朋友参考一下 具体来说包括两个概念. 1 释放该指针指向的内存,只有堆上的内存才需要我们手工释放,栈上不需要. 2 将该指针重定向为NULL.

  • 我有一个理论(非确定性,难以测试,从未发生在实践中)硬件问题报告硬件供应商,其中双字写入特定内存范围可能破坏任何未来的总线传输。 虽然我在C代码中没有任何明确的双词写入,但我担心编译器(在当前或未来的实现中)被允许将多个相邻的词赋值合并为单个双词赋值。 编译器不允许对Volatile的赋值进行重新排序,但(对我来说)不清楚合并是否算作重新排序。我的直觉是这样的,但我以前被语言律师纠正过! 示例:

  • 请考虑以下简单代码: https://godbolt.org/z/i2kby7 您可以看到和都没有优化对的潜在调用。在我的理解中,这是正确的:抽象机器假设变量随时可能发生变化(例如,由于是硬件映射的),因此将初始化常数折叠为检查将是错误的。 > 这里讨论了消除对的读写操作:允许编译器优化本地volatile变量吗?(谢谢内森!)。我认为标准是非常清楚的,那些读写必须发生。但是这些讨论并不包括编译器

  • 例如,你有一个带有气泡排序实现的函数C编译器识别这种模式。是否允许编译器将其更改为另一个示例?比如快速排序。 另一个例子是将从0到的所有数字相加,编译器可以用替换for循环。

  • 问题内容: 我有一个Dockerfile,其中在指令中使用了: arg通过docker-compose传递: 但是,似乎并未针对展开。我之后。 这是检查显示的内容: 问题答案: 问题是只能在构建时使用,而在运行时正在执行。我想现在唯一实现您想要的方法是在Dockerfile中使用该值设置环境变量。