GCC 仅在 static_cast 中警告越界访问

问题描述 投票:0回答:1

仅当在 static_cast 中使用时,即使启用了大多数警告选项,GCC 才会警告

越界数组访问

示例代码(live):

#include <iterator>
#include <numeric>
#include <print>

int main()
{
    int arr[ 5 ] { };
    std::iota( std::begin( arr ), std::end( arr ), 1 );

    //                                  <no warning>                          -<warning>-----
    std::println( "{} at address: {:p}", *(arr - 1), static_cast<const void*>(&( *(arr - 1) )) );
    //                                  <no warning>                         -<warning>-
    std::println( "{} at address: {:p}", arr[ -1 ], static_cast<const void*>(&arr[ -1 ]) );

    int* const ptr { arr + 2 };
    //                                  <no warning>                         -<warning>-
    std::println( "{} at address: {:p}", ptr[ -3 ], static_cast<const void*>(&ptr[ -3 ]) );
}

编译器输出:

<source>: In function 'int main()':
<source>:12:54: warning: array subscript -1 is outside array bounds of 'int [5]' [-Warray-bounds=]
   12 |     std::println( "{} at address: {:p}", *(arr - 1), static_cast<const void*>(&( *(arr - 1) )) );
      |                                                      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<source>:8:9: note: at offset -4 into object 'arr' of size 20
    8 |     int arr[ 5 ] { };
      |         ^~~
<source>:14:78: warning: array subscript -1 is below array bounds of 'int [5]' [-Warray-bounds=]
   14 |     std::println( "{} at address: {:p}", arr[ -1 ], static_cast<const void*>(&arr[ -1 ]) );
      |                                                                              ^~~~~~~~~~
<source>:8:9: note: while referencing 'arr'
    8 |     int arr[ 5 ] { };
      |         ^~~
<source>:18:53: warning: array subscript -1 is outside array bounds of 'int [5]' [-Warray-bounds=]
   18 |     std::println( "{} at address: {:p}", ptr[ -3 ], static_cast<const void*>(&ptr[ -3 ]) );
      |                                                     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<source>:8:9: note: at offset -4 into object 'arr' of size 20
    8 |     int arr[ 5 ] { };
      |         ^~~

例如,我自然也希望看到

*(arr - 1)
的警告。但显然,只有
static_cast
中的表达式(例如
&( *(arr - 1) )
)才会被迂腐地检查是否存在无效访问。

这是 GCC 中的错误吗?因为代码非常简单且明确。我希望编译器至少在这种简单的场景中显示警告。

注意:Clang 更糟糕,仅警告

arr[ -1 ]

c++ gcc clang compiler-warnings access-violation
1个回答
0
投票

这些警告仅在启用优化时才会出现。优化器中发生的抽象解释允许它在编译时检测一些运行时错误。

在这种情况下,您将表达式作为 可变参数 传递,因此尽管您已转换为 const 指针,但

println()
不承诺遵守这一点 - 可变参数在定义的编译时没有特定类型。因此,编译器会看到您正在传递一个“常量指针”,接收函数可能会引用并写入该指针。造成这种情况的不是static_cast,而是
夺取地址
&。强制转换必须符合格式说明符。
在表达式 

*(arr-1)

的情况下,它是读取访问并按值传递(而不是指针),尽管您可能不会获得有用的结果,但您不会修改我们的边界位置 - 因此需要注意警告关于。

您可以使用以下表达式简化测试以证明该行为与静态转换无关:

int x = *(arr-1) ; // No warning - out of bounds read *(arr-1) = 0 ; // warning: array subscript 4611686018427387903 is above array bounds of 'int [5]' int* p = &(*(arr-1)) ; // no warning, juts taken the address, not written to. *p = 2 ; // warning: array subscript -1 is outside array bounds of 'int [5]'

© www.soinside.com 2019 - 2024. All rights reserved.