C++对数组的读取/写入超出界限

C++ read/write to array out of bounds

本文关键字:出界 界限 数组 读取 C++      更新时间:2023-10-16

可能在某个地方已经有了答案,但我找不到。

正如这个问题中所指出的:越界访问数组不会出错,为什么?,C++不强制执行数组边界,而是选择提供未定义的行为。我担心的是这种行为的威力。

所以假设我写了一些简单的程序:

#include <iostream>
int main() {
    int* a = new int[1];
    long large_number = 9223372036854775807l; //2**63 - 1
    for (long i = 0l; i < large_number; i++) {
        std::cout << i << " " << a[i] << std::endl;
    }
    return 0;
}

这将继续打印存储在我的系统上的下一个32位数字(显然,假设是32位大小的int)。当我在我的机器上运行这个程序时,当我大约30000时,程序会出错,我猜这大约是为我的程序分配的内存大小。这就引出了我的问题,它有三个方面:

  1. 是什么阻止我继续读取(而不是写入)此范围之外的值?这种防止阅读系统是特定的吗?编译器特定?

  2. 如果我在操作指针方面很聪明,我是否可以在程序范围之外读取或写入值(显然,没有直接/正常访问这些值的权限)?

  3. 我正在虚拟机上运行所有这些。我可以访问主机上的读/写内存值吗?(如果(2)是否定的,那么这也是否定的)。

请注意,我在一个带有windows主机的ubuntu虚拟机上运行g++5.3.1,没有c++11。

此外,我认识到这个问题可能被认为是一个安全问题(读/写记忆)。我当然没有恶意,但如果这是一个问题,请告诉我,我很乐意结束这个问题。

编辑:以下问题看起来既相关又有趣:在程序分配的内存之外进行访问。(访问其他应用程序的内存)不过,对于程序是否可以在其虚拟内存空间之外读取,似乎还没有达成共识。

  1. 操作系统。操作系统仅将一定范围的虚拟地址映射到物理地址上。在到达映射的虚拟地址范围的末尾之后,尝试访问不存在的虚拟地址会生成SIGSEGV

  2. 没有。至少在任何现代操作系统上都没有。

  3. 除非你能在主机操作系统的虚拟机中发现一个错误并加以利用