STL push_back优化导致数组下标在数组边界之上

STL push_back optimize cause array subscript is above array bounds

本文关键字:数组 下标 边界 push back 优化 STL      更新时间:2023-10-16

测试环境:

  • CentOS 7.0 g++ 4.8.2
  • Arch Linux g++ 4.9.0 20140604 (pre - release)
  • Arch Linux g++ 4.9.1

编译命令:

  1. PASS: g++ -Wall .cpp
  2. FAIL: g++ -Wall -O2 .cpp
  3. PASS: g++ -Wall -O2 t.p p #并将第13行中的2替换为3
  4. PASS: g++ -Wall -O2 t.p p#并注释掉第14行
  5. 通过:g++ - wall - 02 - std = c + + 11 t.cpp # g++ 4.8/4.9

FAIL消息:

t.cpp: In member function ‘void std::vector<_Tp, _Alloc>::_M_insert_aux(std::vecto
<_Tp, _Alloc>::iterator, const _Tp&) [with _Tp = Object; _Alloc = std::allocator<Ob
ject>; std::vector<_Tp, _Alloc>::iterator = __gnu_cxx::__normal_iterator<Object*, s
td::vector<Object> >; typename std::_Vector_base<_Tp, _Alloc>::pointer = Object*]’
t.cpp:17:15: warning: array subscript is above array bounds [-Warray-bounds]
     ~Object() {};
               ^
t.cpp:17:15: warning: array subscript is above array bounds [-Warray-bounds]

t.cpp

#include <vector>                      
class TestCls {                        
public:                                
    TestCls() {};                      
    virtual ~TestCls() {};             
};                                     
class TestCls1 : public TestCls        
{                                      
};                                     
class Object {                         
public:                                
    TestCls    m_member[2];            
    TestCls1   m_member1[2]; // LINE 13, if change to [3] it works.
    TestCls1   m_member2[2]; // LINE 14, if comment out this line, it works.
    Object() {};                       
    ~Object() {}; // LINE 17 the warning line                     
};                                     
class Container {                      
public:                                
    std::vector<Object> m_obj;         
    Container() {};                    
    ~Container() {};                   
};                                     
int main() {                           
        Container con;                 
        Object obj;                    
        con.m_obj.push_back(obj);      
}                                      

这是由GCC生成的一种虚假警告,由于与各种循环优化器传递(例如循环剥离和循环展开)交互的Value Range Propagation(它是生成数组边界警告的中间传递)的问题。正如在链接的各种bug中所提到的,这些也代表了错失的优化机会,但是VRP中的潜在问题(或问题)已经证明对GCC开发人员来说是难以捉摸的。也就是说,将此事件报告给GCC Bugzilla是一个好主意,特别是当您手头有MWE时。

我找到了一个解决办法,但我不知道原因。

// ...
class Object {
public:
    // ...
    ~Object();
};
Object::~Object() {}; // move to outside LINE 19
//...

gcc -Wall启用所有编译器的警告消息。这个选项应该总是被使用,以便生成更好的代码。

那么,试着删除-Wall。例子:

  • with -Wall http://goo.gl/d4cces
  • 无-Wall http://goo.gl/4vY2Un