【问题标题】:Why isn't gcc complaining about array bounds even if requested?为什么即使请求 gcc 也不抱怨数组边界?
【发布时间】:2017-09-26 08:23:19
【问题描述】:

我正在使用 gcc 4.9.0,我希望看到编译器警告我超出数组范围。如果我编译这个

int main()
{
    int table[5]={0};
    table[8] = 1234;
    int x = table[10];
}

使用 g++ -O2 -Wall main.cpp -o main.exe 我只会收到有关未使用 x 的警告:

main.cpp: In function 'int main()':
main.cpp:8:7: warning: unused variable 'x' [-Wunused-variable]
int x = table[10];
   ^

从 gcc 文档 (https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#Warning-Options) 我看到 -O2 和 -Wall 应该启用 -Warray-bounds=1 检查。如果我尝试添加 -Warray-bounds,情况不会改变。事实上,编译器甚至无法识别 -Warray-bounds=1:

g++: error: unrecognized command line option '-Warray-bounds=1'

现在,为什么编译器不给出关于错误地写入/读取数组的警告?为什么编译器不能识别'-Warray-bounds=1'?

【问题讨论】:

  • 无论优化如何,clang 仍然会发出警告。 godbolt.org/g/e6yv89 gcc 不会对此发出警告,无论优化如何:wandbox.org/permlink/gLXfIl7dd87Uwsew
  • 请注意,您链接到的文档是最新版本的 gcc,因此它可能与 4.9 的文档不同。
  • 您不要将=1=0-W 选项一起使用。仅限-Wsome-warning-Wno-some-warning

标签: c++ g++ compiler-warnings


【解决方案1】:

我怀疑缺少警告是因为优化。编译器很容易看到您编写的任何行都不会对程序的行为产生任何影响,因此可能会选择简单地跳过这些行。

看来,检查编译时间已知越界访问的阶段恰好是在删除未使用的代码之后执行的,因此 GCC 从未发现您的错误。

防止这种优化的一个简单方法是声明数组volatile。任何对volatile 对象的写入或读取都必须被编译器视为副作用,因此无法被优化掉。

【讨论】:

    【解决方案2】:

    可能编译器会优化它。尝试制作tablevolatile

    int main()
    {
        volatile int table[]={0,0};
        table[8] = 1234;
        int x = table[10];
    }
    

    产生:

    prog.cc:4:12: warning: array subscript is above array bounds [-Warray-bounds]
         table[8] = 1234;
         ~~~~~~~^
    prog.cc:5:21: warning: array subscript is above array bounds [-Warray-bounds]
         int x = table[10];
                 ~~~~~~~~^
    

    这是live example


    来自-Warray-bounds docs:

    它警告数组的下标总是越界

    我的猜测是,当访问从未真正发生时,g++ 决定不发出警告。


    事实上,编译器甚至无法识别 -Warray-bounds=1:

    g++: error: unrecognized command line option '-Warray-bounds=1'

    g++-4.9.0 不支持-Warray-bounds=n 格式的命令,但它可以与-Warray-bounds 一起正常工作。从 g++-5.1.0 开始支持 -Warray-bounds=n

    【讨论】:

    • 代码仍在编译中,所以奇怪的是优化会使警告不显示。无论优化级别如何,Clang都会发出警告,这对我来说似乎更正确。 godbolt.org/g/e6yv89
    • 我关闭了您示例的优化并删除了 volatile 关键字,但仍然没有收到警告:wandbox.org/permlink/gLXfIl7dd87Uwsew
    • @xaxxon -Warray-bounds 需要 -ftree-vrp,默认情况下使用 -O2
    • @xaxxon 请查找-ftree-vrp 的文档,可能它需要一些其他标志:它不像仅与-O0 一起启用它那么容易
    猜你喜欢
    • 1970-01-01
    • 2016-02-27
    • 1970-01-01
    • 2017-01-17
    • 1970-01-01
    • 2013-05-08
    • 2022-10-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多