GCC` -fsanitize = bounds`与`std :: array`的奇怪行为

时间:2016-11-18 12:49:41

标签: c++ arrays g++

我正在尝试使用-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,结果相同。

2 个答案:

答案 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]显示为错误,如预期的那样。