考虑这个简单的程序:
#include <array>
#include <iostream>
#include <cstdlib>
int main(int argc, char* argv[]) {
std::array<int, 5> arr = {0, 1, 2, 3, 4};
int idx = std::atoi(argv[1]);
int val = std::atoi(argv[2]);
arr[idx] = val;
for (auto i=0u; i <= idx; i++) {
std::cout << "arr[" << i << "] = " << arr[i] << std::endl;
}
}
如果我像这样编译并将其与 GCC 6.3.1 链接:
g++ -O0 -std=gnu++14 -fsanitize=undefined example.cpp
并像这样运行它:
a.out 5 98
我没有收到任何警告,即使我正在写入和读取 'arr' 末尾之后的一个元素(数组在索引 4 处结束)。
如果我运行:
a.out 6 98
我收到一条警告,提示“索引 6 超出类型“int [5]”的范围。在这种情况下,我正在编写和读取 'arr' 末尾之后的两个元素。
为什么非一个案例不会引发错误?我猜是因为数组末尾的一个元素是有效的内存地址(即迭代器可以指向它?)。您能否推荐任何其他可以可靠地检测到一个元素的越界访问的工具?
编辑
我也可以运行:
g++ -O0 -std=gnu++14 -fsanitize=bounds-strict example.cpp
而且我看到了相同的行为,即一个元素的越界访问不会触发警告,但是,两个元素的越界访问会触发。这是我试图理解的部分。