【问题标题】:Why segmentation fault does not occur?为什么不发生分段错误?
【发布时间】:2016-03-18 06:02:57
【问题描述】:
#include <stdio.h>

int main(void){
  char *temp = malloc(11);
  strcpy(temp, "123456789");
  free(temp);
  printf("%c\n", *temp);
  return 0;
}

在上面的代码中,为什么我在访问尚未分配的内存时不会出现分段错误。而且打印出来的字符是空的?不应该是1吗?

【问题讨论】:

  • 您是在要求我们定义未定义的行为吗?
  • 未定义行为是未定义的行为,任何事情都可能在它被调用后发生。避免它。
  • 它可以是任何东西。无法保证触发 UB 后的输出。
  • 所以分段错误可能发生也可能不发生?
  • 没错,你的磁盘可能会被格式化,或者盒子会烧掉...... ;-)

标签: c segmentation-fault malloc free


【解决方案1】:

向@I3x 答案添加一个元素。

例如,与取消引用 NULL 不同,从同一进程中取消引用来自 malloc 的地址 - 即使该地址刚刚被释放 - 是从进程的虚拟地址空间中取消引用地址,地址那是/刚才对进程可见的。因此,在这种情况下,触发段错误的可能性较小。

但是,在 free 运行之后,操作系统会认为该内存段未使用,准备好再次分配,甚至由内存分配系统本身立即使用。这可能就是您在 free 发生后在该位置获得不同值的原因。

该段可能被分配给另一个进程,或者对最初分配它的进程不可用,从而触发页面错误 => segfault。

无论如何,没有理由“欺骗”系统试图继续使用已归还给操作系统的内存区域。

再重复一遍:“相似”意味着未定义的行为。你可能不会得到一个段错误,你可能会得到一个。字节可能会改变,也可能不会。但是,无论如何,在 free 之后,该内存不再可用。完全没有。不要这样做。

【讨论】:

    【解决方案2】:

    一旦你free() 指针temp,它的值是不确定的。 访问它是undefined behaviour。无法保证未定义的行为会导致分段错误。

    【讨论】:

    • 那么你对输出有什么看法呢?这取决于我的内存使用情况吗?
    • @lplouis 查看释放后的第一个字节,很可能会让您查看内存分配管理本身。
    • 吹毛求疵:“Accessing”可能更好地理解为“dereferencing”。
    • @lplouis 你不能对输出说什么,它(也)是不确定的。
    • @lplouis 对于未定义的行为,没有“这就是它的工作原理”的解释。您观察到的内容可能会在您下次运行或更改优化级别或向程序中添加更多代码时发生变化。关键是你无法确定行为。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-04
    • 2017-10-14
    • 1970-01-01
    • 2011-01-27
    • 2020-11-01
    • 2013-05-01
    相关资源
    最近更新 更多