G 4.8.5带负数组索引的循环优化错误



我怀疑我找到了一个G 优化错误,该错误与用负索引的对象(structs(中的数组相关。

在下面的节点是结构,它具有阵列 it(在我的真实代码中,它是跳过列表的节点,其指针数和数据包的大小为基础差异代码的可变且未知,因此决定将指针放在对象引用和数据包之前 - 在此之后很长 - 在对象之后(。

#include <iostream>
#include <stdlib.h>
class Node {
public:
  unsigned int ptr[1]; // really an array going backwards
  long datum; // This seems to be necessary for the bug to surface                                                                                                                                       
};
class NodeList {
public:
  Node* hdr;
  NodeList() {
    void* p_v = malloc( sizeof(Node) + 32 * sizeof( unsigned int ) );
    hdr = (Node*)((char*)p_v + 32 * sizeof(unsigned int));
    hdr->ptr[-5]=100;
  }
  void setNodes() {
    int nn=0;
    while( rand() > 20 && nn<9 ) {
      nn++;
    }
    if( nn < 9 ) {
      nn = 9;
    }
    // It is a logical truth that nn = 9 here                                                                                                                                                            
    //nn = 9; // IF THIS IS UNCOMMENTED EVERYTHING WORKS!                                                                                                                                                
    std::cout << "nn=" << nn << " (should be 9) " << std::endl;
    int ctr = 0;
    for( int i=0; i<=nn; i++ ) {
       ctr++;
       hdr->ptr[-i]=0;
    }
    std::cout << "ctr was incremented " << ctr << " times (should be 10) and hdr->ptr[-5] = " << hdr->ptr[-5] << " (should be 0)n";
  }
};
int main( int argc, char** argv ) {
    NodeList list;
    list.setNodes();
 }

预期输出的CTR已增加10次,HDR-> ptr [-5]为0。优化代码仅通过一次循环(即不循环(,然后将Ptr-> Hdr [-5]丢弃为100。这是一个错误。

-fno-aggressive-gloop-optimizations似乎可以修复它,但是如果输出代码正确,显然会更好。

我将其放在这里(a(验证这是一个错误(例如,我应该如何报告它,以及它是否已在以后的发行中进行了固定(,以及(c(允许在Centos 7(或其他任何其他具有4.8的发行版(上遇到最令人沮丧且耗时的问题的人请参阅确认他们已经撞到了同伴的错误!

在这里必须小心'数组'的含义。数组是定义为

的任何东西
some_type arr[number];

,但不是

some_type*ptr = some_address;

负索引与正索引没有什么不同,ptr[n]被解释为*(ptr+n)(您甚至可以在C中使用n[ptr](。因此,当索引时,使用指针算术。

C和C 中的不确定的行为(UB(,无论是如何实现的,都可以在数组的边界之外访问元素。例如

some_type arr[10];
some_type*ptr = arr+5;
some_type foo = ptr[-4];    // ok, access to arr[1]
some_type bar = ptr[-6];    // UB, out-of-bound access
some_type val = arr[-1];    // UB, out-of-bound access

最新更新