首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >带有负数组索引的g++ 4.8.5循环优化错误

带有负数组索引的g++ 4.8.5循环优化错误
EN

Stack Overflow用户
提问于 2017-05-30 07:44:37
回答 1查看 168关注 0票数 2

我怀疑我发现了一个g++优化错误,它与带有负索引的对象(structs)中的取消引用数组有关。

在下面的结构中,Node是在它前面有一个数组的结构(在我的实际代码中,它是一个Skip列表的节点,它的指针数量和数据包大小都是可变的,并且对底层的SkipList代码来说是未知的,因此决定将指针放在对象引用之前,而数据包放在对象之后很长时间)。

代码语言:javascript
复制
#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-咄咄逼人的循环优化似乎修复了它,但如果输出代码是正确的,显然会更好。

我把这个放在这里是为了(a)确认这是一个bug,因为我是这里的新手,这是我的第一个问题,(b)问任何熟悉gcc开发社区的人,该做些什么。我应该如何报告它,以及它是否在以后的版本中被修复),和(c)允许那些在CentOS 7上经历过这个最令人沮丧和耗费时间的问题的人(或任何其他版本,4.8)看到他们已经从同病者那里感染了一个bug!

EN

回答 1

Stack Overflow用户

发布于 2017-05-30 08:35:13

在这里,对于“数组”的含义,我们必须小心。数组是任何定义为

代码语言:javascript
复制
some_type arr[number];

但不是像

代码语言:javascript
复制
some_type*ptr = some_address;

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

无论如何实现,在C和C++中访问数组边界外的元素都是未定义的行为(UB)。例如

代码语言:javascript
复制
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
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44256413

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档