【问题标题】:Why no segfault shows in this program?为什么这个程序没有段错误显示?
【发布时间】:2020-10-16 22:02:25
【问题描述】:

据我了解,分段错误发生在程序因尝试访问不可用的内存而崩溃时。我知道第一个程序(A.c)是错误的,因为 sizeof(a) 是 4bytes * 5 = 20bytes。由于无限循环,第二个程序(B.c)是错误的。当我运行 A.out 时,我没有收到错误,只是结果不正确(结果也不一致)。但是当我运行 B.out 时,我得到了分段错误。

我预计 A 会出现与 B 相同的分段错误,因为它们都访问超出范围的内存数据。我最好的猜测是 int a[5] = {1, 2, 3, 4, 5}; 可能会导致这种情况。谁能告诉我为什么?

交流

int main() {
    int a[5] = {1, 2, 3, 4, 5};
    unsigned total = 0;
    printf("size of a is %lu\n", sizeof(a));
    printf("total was %d\n", total);
    for (int j = 0; j < sizeof(a); j++) {
        total += a[j];
    }
    printf("sum of array is %d\n", total);
}

B.c

int main() {
    int a[20];
    for (int i = 0; ; i++) {
        a[i] = i;
    }
}

【问题讨论】:

  • B 中的无限循环。但操作系统会在分段错误时发现您。
  • 没错。但我想知道为什么 A 不会产生分段错误。
  • 看我的回答。下。
  • 没有保证操作系统会为您找到错误。如果你幸运的话,你很早就会撞车。如果运气不好,您在发货时会崩溃。

标签: c memory-leaks segmentation-fault


【解决方案1】:

澄清一下:分段错误并不是因为不断检查您的代码是否超出范围而出现的。相反,它是一种 CPU 级别的机制,涉及告诉 CPU 在 RAM 的哪个区域应该发生某些事情并捕获违反此规则的情况。这个 RAM 区域也不完全是代码或数据的大小。因此,在某些情况下,访问超出范围的日期是访问 CPU 可能访问的内存,例如,另一个变量或数组存储在您访问的变量或数组之后,索引太高,甚至是一些未使用的内存,因为允许的内存块可能具有向上舍入以匹配某些对齐边界的大小。

我认为int a[5] = {1, 2, 3, 4, 5}; 不会导致您的应用程序失败。如果你忽略了= {1, 2, 3, 4, 5},你仍然定义了一个有效的内存块来访问,它的内容只是没有定义。

您是否期望 A 失败,因为您使用 sizeof(a) 而不是 sizeof(a)/sizeof(int)?假设int 是 4 个字节,这将导致 A 访问 4 倍于允许的内存。这很可能仍然在堆栈内存中,您不会导致分段错误。在 B 中,您有一个无限循环,这导致它的地址超出堆栈大小,这将导致分段错误。

【讨论】:

    【解决方案2】:

    两者都是未定义的行为。 UB表示从C的角度无法确定运算的结果。

    访问未分配的内存可能但不一定会导致段错误。

    但试图理解这两个 sn-ps

    一个。您可以访问距离数组边界不远的内存。 OS 不会阻止程序访问该区域。什么都没有发生。

    b.最终你到达受操作系统保护的内存。发生段错误。

    【讨论】:

      猜你喜欢
      • 2011-12-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-06
      • 2019-01-07
      • 1970-01-01
      • 2012-04-20
      • 2017-11-25
      相关资源
      最近更新 更多