我正在尝试使用-fsanitize=bounds
选项在我的代码中找出超出范围的问题,但我遇到了奇怪的行为:
例如,在以下代码中:
#include <cstdlib>
#include <array>
int main (int, char **)
{
std::array <char, 1> a;
const char b = a [X]; // X <--- put index here!
return EXIT_SUCCESS;
}
使用选项编译:{{1}}。
如果我尝试访问索引大于1的元素,则报告错误:
$ g++ -std=c++11 -fsanitize=bounds -O0 main.cpp -o main
。
但是如果我尝试访问索引为1的元素 - 一切正常并且没有报告错误。
这是预期的行为,可能是我错过了什么?
测试的例子如下:
- /usr/include/c++/5/array:53:36: runtime error: index 2 out of bounds for type 'char [1]'
;
- $ g++ --version g++ (Ubuntu 5.4.0-6ubuntu1~16.04.2) 5.4.0 20160609
。
UPD
我在GCC 6中尝试了$ g++ --version g++ (Ubuntu 6.2.0-5ubuntu12) 6.2.0 20161005
,结果相同。
答案 0 :(得分:1)
我无法立即找到这方面的文档(或者,实际上,任何类型的强大文档),但这很可能是因为这是该功能的实现细节。获得一个过去的指针是合法的,因此实现无法捕获这一点。似乎实现通过查看指针来工作,而不是等待这样的指针被解除引用(如果你考虑如何创建-fsanitize=bounds
,这是有道理的。)
简而言之,这可能只是对工具的限制。
在GCC 6中,您可以尝试-fsanitize=bounds-strict
,这会增加工具的强度(包括添加对检测对柔性成员类数组的OOB访问的支持)。
我无法判断这是一个库还是编译器问题,但无论哪种方式都值得注意,同一问题目前是针对clang(#21485)的开放式错误,并且评论中的假设与我匹配上面的乱跑。
A third-party article on ubsan也暗示这最终是预期的行为。
答案 1 :(得分:0)
来自https://gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.html
-fsanitize =界定 此选项启用数组边界的检测。检测到各种越界访问。灵活的阵列成员,灵活 数组成员类数组,以及带静态变量的初始值设定项 存储没有检测。
使用X&gt; 1进行此检查(数组越界)触发,正如预期的那样,因为'a'char声明,size = 1。
正如那样说,正如Orbit的OrLights Races所说,这不是答案。但是为读者提供了一些信息。
案例X == 1是一个过去的事实使我想到了迭代器,其中允许一个过去。 IOW,似乎GCC清理工具获得了一个迭代器来测试,而不是参考a [X]。
@Gluttton确认使用类似C的数组而不是std :: array的情况a [1]显示为错误,如预期的那样。