Thread: Vector.size() vs iterating

  1. #1
    Carnivore ('-'v) Hunter2's Avatar
    Join Date
    May 2002
    Posts
    2,879

    Vector.size() vs iterating

    Given a std::vector<MyClass> named myVec:
    Code:
    // Loop version 1
    for (int i = 0; i < myVec.size(); ++i) {
       // Do something with myVec[i]
    }
    
    // Loop version 2
    for (std::vector<MyClass>::iterator it = myVec.begin();
          it != myVec.end(); ++it) {
       // Do something with *it
    }
    
    // Loop version 3
    for (auto &x : myVec) {
       // Do something with x
    }
    Tracing my code in a debugger I am getting size = 0, loop version 1 does not execute, and loop versions #2 and #3 enter the loop and cause an access violation.

    My suspicion is that I'm writing out of bounds somewhere and corrupting the vector's internal state, but wanted to check if you guys know of any legitimate case when this could happen.

    Thoughts?
    Last edited by Hunter2; 03-28-2014 at 12:16 AM. Reason: clearer title
    Just Google It. √

    (\ /)
    ( . .)
    c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.

  2. #2
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    No, begin() always returns the same iterator as end() if the vector is empty. You did something.

  3. #3
    Carnivore ('-'v) Hunter2's Avatar
    Join Date
    May 2002
    Posts
    2,879
    Blah. Yeah it looks like something is definitely broken. empty() returns false, size returns 0, begin() returns a reference to address 0x01, end() returns address 0, and resize(1) gives another access violation.

    =/
    Just Google It. √

    (\ /)
    ( . .)
    c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.

  4. #4
    Registered User
    Join Date
    Dec 2006
    Location
    Canada
    Posts
    3,226
    Uh. What compiler is that?

    And a minimum compilable program that shows this behaviour?

  5. #5
    Registered User
    Join Date
    Dec 2006
    Location
    Canada
    Posts
    3,226
    My guess is you have a pointer to a vector, but didn't actually allocate a vector.

  6. #6
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    If case your debugger doesn't trap accesses to operator [] in your vector, it might be willing to trap exceptions. Try using .at() instead of [] to access elements to track if you do make some out-of-bounds accesses.
    Btw, in example #2, you can replace "std::vector<MyClass>::iterator" with "auto" since you are using C++11 anyway.

    Of course, it does sound a little too convenient, so perhaps it is a non-allocated pointer or even a null pointer to a vector.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  7. #7
    Carnivore ('-'v) Hunter2's Avatar
    Join Date
    May 2002
    Posts
    2,879
    @cyberfish -
    a) Xcode, so I guess LLVM. I haven't been able to repro yet with a smaller program.
    b) It's a non-pointer member variable of an instance which is declared as a non-pointer static member of a method, so it should not be running into unallocated issues.

    @Elysia -
    This is happening shortly after some deserialization code (the template stuff you helped with some time ago, actually ).
    I don't actually index into the arrays very much in this code, it looks more like the following:
    Code:
    // vector<char> data;
    data.resize(bytesToRead);
    reader.read(&(data[0]), bytesToRead);
    Which seems legitimate to me.

    I'll keep poking at it and see if I can get any more clues.
    Just Google It. √

    (\ /)
    ( . .)
    c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.

  8. #8
    Registered User
    Join Date
    Dec 2006
    Location
    Canada
    Posts
    3,226
    b) It's a non-pointer member variable of an instance which is declared as a non-pointer static member of a method, so it should not be running into unallocated issues.
    In that case, maybe memory corruption is going on? Eg. a buffer overflow somewhere else in the program.

  9. #9
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Well then, I'd use a debugger.
    First, after your read, check the consistency of the vector. Does it reports its size as expected? If so, good. Then we have a good staring point.
    Now, if you look into the internals of the vector, you will probably find a size and a pointer. Set a data breakpoint such that the debugger breaks whenever the size of pointer of the vector is modified, then run your code.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  10. #10
    Carnivore ('-'v) Hunter2's Avatar
    Join Date
    May 2002
    Posts
    2,879
    After poking around a lot more, it seems things are broken right off the bat.

    At risk of sounding really dumb:
    Do I explicitly need to define constructors that chain down the inheritance hierarchy and invokes all the parent classes' default constructors? The following 'equivalent structure' to my class hierarchy seems to work fine when run in isolation, but not in my actual classes/program. Not sure if I'm just getting lucky in my test program with default values (also, built for x86 vs. built for iOs).

    Code:
    class Virt {
    public:
        virtual void deserialize() = 0;
    };
    
    class Foo {
    public:
        int x;
        int y;
    };
    
    class Base : public Virt {
    protected:
        vector<Foo> foos;
    };
    
    class MyClass : public Base {
    public:
        virtual void deserialize() { }
        static void test();
    };
    
    void MyClass::test()
    {
        MyClass m;
        cout << m.foos.size() << endl;
    }
    
    int main(int argc, const char * argv[])
    {
        MyClass::test();
        return 0;
    }
    Just Google It. √

    (\ /)
    ( . .)
    c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.

  11. #11
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by Hunter2 View Post
    Do I explicitly need to define constructors that chain down the inheritance hierarchy and invokes all the parent classes' default constructors?
    No, you don't. Each constructor is implicitly invoked.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  12. #12
    Carnivore ('-'v) Hunter2's Avatar
    Join Date
    May 2002
    Posts
    2,879
    Yeah I'm completely baffled. Test code, with class names changed:
    Code:
    void ClassX::method() {
        MyClass inst;
        cout << inst.nodes.size() << endl;
    
        MyClass::test();
    }
    
    void MyClass::test() {
        MyClass sharedInstance;
        cout << sharedInstance.nodes.size() << endl;
    }
    Debugger session:
    Code:
    // From ClassX::method()
    // Stepped into vector constructor after it initializes __begin_ and __end_ to nullptr. 
    (lldb) p &__begin_
    (pointer *) $0 = 0x27de8bbc
    (lldb) p &__end_
    (pointer *) $1 = 0x27de8bc0
    
    // Breakpoint just after constructor returns
    (lldb) p &(inst.nodes.__begin_)
    (pointer *) $4 = 0x27de8bbc
    (lldb) p &(inst.nodes.__end_)
    (pointer *) $5 = 0x27de8bc0
    
    // Cout of inst.nodes.size()
    0
    
    // From MyClass::test() in same session immediately afterwards
    // Stepped into vector constructor after it initializes __begin_ and __end_ to nullptr.
    (lldb) p &__begin_
    (pointer *) $6 = 0x27de8a80
    (lldb) p &__end_
    (pointer *) $7 = 0x27de8a84
    
    // Breakpoint just after constructor returns
    (lldb) p &(sharedInstance.nodes.__begin_)
    (pointer *) $10 = 0x27de8a98  // Wrong address?
    (lldb) p &(sharedInstance.nodes.__end_)
    (pointer *) $11 = 0x27de8a9c  // Wrong address?
    
    // cout of sharedInstance.nodes.size()
    -146087323  // obviously wrong
    
    (lldb) p sharedInstance.nodes.__end_
    (std::__1::__vector_base<GLNode, std::__1::allocator<GLNode> >::pointer) $13 = 0x27de8ae4
    (lldb) p sharedInstance.nodes.__begin_
    (std::__1::__vector_base<GLNode, std::__1::allocator<GLNode> >::pointer) $14 = 0x27de8ae8
    
    (lldb) p ((int)sharedInstance.nodes.__end_ - (int)sharedInstance.nodes.__begin_)
    (int) $16 = -4  // Different from .size()
    
    (lldb) p *(int**)0x27de8a80  // Original address of __begin_
    (int *) $17 = 0x00000000  // as originally initialized in constructor
    (lldb) p *(int**)0x27de8a84  // Original address of __end_
    (int *) $18 = 0x00000000  // as originally initialized in constructor
    The std::vector implementation has .size() as:
    Code:
    size_type size() const _NOEXCEPT
            {return static_cast<size_type>(this->__end_ - this->__begin_);}
    I would have assumed that the debugger was just somehow getting the wrong address for .nodes.__begin_ and __end_, but I don't know where .size() is getting its value from - and it doesn't match what I calculate from the values at the 'wrong' addresses either.
    Just Google It. √

    (\ /)
    ( . .)
    c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.

  13. #13
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    It would be nice if you could post a small compilable example that demonstrates the problem.
    From your example, consider that you are constructing two instances of the class and that those do not share the vector! Furthermore, the instance goes out of scope as soon as test ends.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  14. #14
    Carnivore ('-'v) Hunter2's Avatar
    Join Date
    May 2002
    Posts
    2,879
    Yeah, this is just extracted out of the section of code that I've been poking and pulling strings on to try and get more info out of. I realize that it does nothing useful in its current state, but was hoping you (or someone) might have seen similar things before when debugging. I'll try and get a smaller compilable case and post back.
    Just Google It. √

    (\ /)
    ( . .)
    c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.

  15. #15
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Not much going on in your example except that you create two instances and print out the different instance's vectors' sizes. I also have problem connecting your debug output to the different points in the source.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Vector Size
    By Ducky in forum C++ Programming
    Replies: 11
    Last Post: 12-10-2013, 03:43 PM
  2. Using stl's vector.size() with printf
    By manuels in forum C++ Programming
    Replies: 11
    Last Post: 08-18-2009, 07:47 PM
  3. STL question: vector size (2 dimension)
    By codeguy in forum C++ Programming
    Replies: 3
    Last Post: 02-08-2008, 05:52 AM
  4. Vector their size and declarations
    By strickey in forum C++ Programming
    Replies: 13
    Last Post: 12-29-2004, 08:45 AM
  5. getting size of a vector
    By abrege in forum C++ Programming
    Replies: 1
    Last Post: 03-31-2003, 09:48 PM