4

I have the following code:

Where I stupidly iterate over a container (self-written). If I compile this function with the cout it works and the program terminates correctly after the iteration! Note: The cout does not interfere with the self-made container! If I then comment it out, the test starts to take infinitely long and does not terminate! My eyeballs where almost dropping inside my head! What the hack is going on here??? My first guess was, that the compiler does something wrong? (but why?) or that maybe branch prediction plays me wrong and somehow increments the iterator twice? (which will result in no end() iterator).

I can really not explain what is going on?

    int loops = 100;
    int n = 0;

        RangeTypes<Type>::ContainerType range(a);
        INIT_TIMER
        START_TIMER
        for(int i=1; i<loops; i++) {
            for(auto it=range.begin(); it != range.end(); ++it) {
                n +=  *it;
                //std::cout << i << std::endl;
            }
        }
        STOP_TIMER("Range: ")

Actually the RangeType Container looks like this, and is pretty simple, it takes a range, and iterates from start to end!

template<typename Type>
struct RangeTypes {
    using  RangeType = std::pair<Type,Type> ;

    class Iterator {
    public:

        Iterator(): m_rangePtr(nullptr), m_currVal(0) {};
        ~Iterator() {};
        Iterator(RangeType & range, bool atEnd=false): m_rangePtr(&range) {
            if(atEnd) {
                m_currVal = m_rangePtr->second;
            } else {
                m_currVal = m_rangePtr->first;
            }
        };

        /** pre-increment ++it
        * Allow to iterate over the end of the sequence
        */
        Iterator & operator++() {
            if(m_rangePtr) {
                ++m_currVal;
            }
            return *this;
        }

        /** post-increment it++ */
        Iterator operator++(int) {
            Iterator it(*this);
            operator++();
            return it;
        }

        bool operator==(const Iterator &rhs) {
            if(m_rangePtr) {
                if(m_rangePtr == rhs.m_rangePtr ) { // if sequences are the same
                    return m_currVal == rhs.m_currVal;
                }
            }
            return false;
        }

        // Return false if the same!
        bool operator!=(const Iterator &rhs) {
            return !(*this==rhs);
        }

        // get current value;
        Type operator*() {
            return m_currVal;
        }

    private:
        RangeType * m_rangePtr;
        Type m_currVal;
    };

    class ContainerType : public RangeType {
    public:

        typedef Iterator iterator;

        ContainerType(RangeType & range ): RangeType(range) {
            // if range wrong, set to no range!
            if(this->first > this->second) {
                this->first = 0;
                this->second = 0;
            }
        }
        iterator begin() {
            return iterator(*this);
        };
        iterator end() {
            return iterator(*this,true);
        };
    };
};

HERE IS THE MWE: Compiled Example

Thanks for any help!!

Gabriel
  • 8,990
  • 6
  • 57
  • 101
  • 4
    Smells to me like stack/heap corruption. – mrks Jun 04 '14 at 17:47
  • Ok that might be!... hm... Thanks for the hint – Gabriel Jun 04 '14 at 17:48
  • also: `for(auto&x : range) {...}` if you are allowed to use c++11 :) – Andro Jun 04 '14 at 17:48
  • Yes, also for ``for(auto&x : range) {...}`` – Gabriel Jun 04 '14 at 17:53
  • @Gabriel I didn't meat that the loop format would solve the problem, just a little suggestion for the future. – Andro Jun 04 '14 at 17:54
  • 1
    I dont see any heap corroption in my code, ok I prepare a MWE – Gabriel Jun 04 '14 at 17:56
  • I added the MWE, and suprisingly it works on IDEONE :-) – Gabriel Jun 04 '14 at 18:03
  • 2
    Your "first guess", should have been that the code is incorrect. Occam's razor applies; the probability incorrect code generation by the compiler or an issue with branch prediction are vanishingly small compared to human error. – Clifford Jun 04 '14 at 18:12
  • @Clifford "vanishingly" might be too strong a word. Compilers do have bugs (not that this is likely to be one). Maybe "exceedingly" is better. – Dan Nissenbaum Jun 04 '14 at 18:22
  • @DanNissenbaum : "vanishingly" in the sense that probablity of compiler error divided by probably of code error is a very small number - so much so that it would never be your "first guess". – Clifford Jun 04 '14 at 18:27
  • 1
    Does you MWE not terminate on your local compiler? – dyp Jun 04 '14 at 18:27
  • No unfortunately it does not .-) – Gabriel Jun 04 '14 at 18:32
  • I would agree with DanNissenbaum and Clifford. I was at the end of my expertise... thats why I guessed this :-), of course its hopefully a stupid programming error – Gabriel Jun 04 '14 at 18:34
  • It may be just me being too stupid, but using this many shadowing terms in such a small piece of code, which I struggle to dig through, strikes me as not a good idea when you try to track down an error. I stare at your ctors and mentally try to re-insert what they really stand for, and it's hard (for me). I had this exact issue recently, and I wish I remembered what was wrong (in my case, it was obviously my coding error). – gnometorule Jun 04 '14 at 18:36
  • 1
    So you use g++ locally.. which version? – dyp Jun 04 '14 at 18:40
  • 1
    Your MWE works fine with g++ 4.7.2, g++ 4.9.0, clang++ 3.5, icpc 14.0; I don't get an infinite loop. – Ali Jun 04 '14 at 20:32
  • OK, gcc 4.7.3 by me it does not work, with gcc 4.8 it works, So it seems there is definitely a bug in gcc 4.7.3 – Gabriel Jun 05 '14 at 06:49
  • Did you try running valgrind? this could be some undefined behavior or other mem corruption – Leeor Jun 05 '14 at 18:25
  • no i did no try valgrind, what would you suggest in running with valgrind? have no experience with this?... – Gabriel Jun 07 '14 at 18:57

0 Answers0