为什么 C++ 数组中的溢出依赖于操作系统/编译器?

时间:2020-12-24 18:45:40

标签: c++ arrays

我有一个关于 C++ 数组的问题。我正在学习 C++,在“数组”部分我遇到了一些我无法理解的东西。

假设我们有一个包含 5 个元素的整数数组。讲师说,在下一行中,如果我们尝试获取数组的第五个索引的输入,我们无法知道会发生什么(例如崩溃或诸如此类),因为它取决于操作系统和编译器。

int testArray[5] {0};
std::cin >> testArray[5];

你能告诉我为什么这种情况依赖于操作系统/编译器吗?

2 个答案:

答案 0 :(得分:3)

C++ 是一种系统语言。它不要求对操作进行任何检查:正确实现的程序将受到不必要的检查的阻碍,例如,验证数组访问是否在边界内。检查将包括每次访问可能需要的条件(除非优化器可以看到可以省略某些检查)和可能还有额外的内存,因为系统需要表示检查数组的大小。

由于没有检查,您最终可能会在为相关数组分配的内存之外操作字节。这可能会覆盖用于其他事物的值,或者它可能会访问超出页面边界的内存。在后一种情况下,系统可能会设置为导致分段错误。在前一种情况下,它可能会访问其他未使用的内存,并且可能没有不良影响。 ...或者它可能会以某种方式修改堆栈,从而阻止程序从函数正确返回。但是,堆栈的布局方式取决于许多方面,例如所使用的 CPU、给定系统上的调用约定、一些编译器首选项。为了避免妨碍正确的程序,在执行非法操作时没有强制行为。相反,程序的行为变得未定义,任何事情都可以发生。

行为未定义是一种不好的行为,如果是你造成的。简单的解决方案不是导致未定义的行为(是的,我知道,说起来容易做起来难)。然而,让行为未定义通常是良好的性能,它也使不同的实现能够实际定义行为以做一些有用的事情。例如,它使实现检查未定义的行为并报告这些情况是合法的。做一些事情来检测未定义的行为是,例如,由某些编译器提供的 -fsanitize=undefined 完成(我认为这不会导致检测到所有类型的未定义行为,但它肯定会检测到某些类型的未定义行为)。< /p>

答案 1 :(得分:0)

数组不应该被索引到外部。 C++ 决定不实际检查这些索引,这意味着您可以读取数组的边界。它只是告诉您不应该这样做,并将越界检查委托给程序员以提高速度。

由于编译器和操作系统以及许多其他因素可以决定内存的布局方式,因此读取数组边界基本上可以做任何事情,包括提供垃圾值、段错误或 summon nasal demons