越界读取可能返回垃圾值或相邻变量值,越界写入可能覆盖关键数据甚至触发崩溃;std::array::at()可捕获越界而operator[]不会;编译器警告不可靠,ASan需显式开启,唯一可靠防线是手动边界判断。

越界读取可能返回垃圾值或相邻变量值
用 arr[10] 访问长度为 10 的 int arr[10],编译器会算出地址 &arr[0] + 10 * sizeof(int),然后直接读那块内存。这块内存可能存着别的局部变量、函数参数、甚至栈上未初始化的随机字节——结果完全不可控。比如 int a[5]; int flag = 1; a[5] = 0; 后,flag 可能被悄悄改成 0,但程序不崩溃,逻辑却错得离谱。
越界写入可能覆盖关键数据甚至触发崩溃
写越界比读越界更危险,因为会真实修改内存:
-
scores[5] = 60;(int scores[5])很可能覆盖紧邻其后的变量,比如循环计数器、返回地址或栈帧控制信息 - 若写入位置是只读页(如代码段或空闲内存),OS 会立即抛出
Segmentation fault或Access violation - 在嵌入式或内核场景下,可能直接导致设备死机或数据静默损坏,而非报错
std::array::at() 能捕获越界但 operator[] 不会
std::array 的两种访问方式行为完全不同:
-
arr[i]:和原生数组一样,无检查,未定义行为 -
arr.at(i):运行时检查,越界时抛std::out_of_range异常,可被捕获 - VS Debug 模式下
operator[]可能触发断言,但 Release 下彻底失效
别指望编译器帮你拦住 arr[10]——它连警告都不一定给,尤其当索引是变量时。
立即学习“C++免费学习笔记(深入)”;
编译器警告不可靠,依赖静态分析不现实
现代编译器(GCC/Clang/MSVC)对越界只有有限的静态检测能力:
- 仅对明显常量索引(如
arr[10]配int arr[10])可能发-Warray-bounds或 C6385 - 一旦索引来自变量、函数返回值或用户输入,全部沉默
- ASan(AddressSanitizer)能 runtime 检测,但必须显式开启且仅用于测试
真正可靠的防线只有你写的边界判断:if (i >= 0 && i ,或者统一用 <code>at() + 异常处理——别省这三行代码。


















