为什么这个程序没有段错误?

Why no segfault shows in this program?

根据我的理解,当程序因尝试访问不可用的内存而崩溃时会发生分段错误 it.I 知道第一个程序(A.c)是错误的,因为 sizeof(a)是 4 字节 * 5 = 20 字节。第二个程序(B.c)是错误的,因为无限 loop.When I 运行 A.out,我没有得到错误的结果(结果也不一致)。但是当我 运行 B.out 时,我得到了分段错误。

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

A.c

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;
    }
}

澄清一下:分段错误并不是由于不断检查您的代码是否超出范围而出现的。相反,它是一种 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 中,您有一个无限循环,这导致它超出堆栈大小进行寻址,这将导致分段错误。

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

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

但试图理解这两个片段

一个。您访问离数组边界不远的内存。 OS不阻止这个区域被程序访问。没有任何反应。

b。最终你到达了受 OS 保护的内存。发生段错误。