Watch out for std::vector size

A quick reminder based on my experience. Recently I stumbled upon this great snippet, which lets me send graphics card a vector of data:

It is a useful one, but at first I started getting problems when calling OpenGL drawArrays* methods.

It took me a while to realize the problem appears because of the way I filled the vector with data. Of course real code was quite complicated, but it boils down to:

  1. Allocate vector
  2. Reserve memory using precalculatedSize
  3. Get iterator: std::vector::begin
  4. Loop with unsigned int i = 0..precalculatedSize-1, set data[i]

Looks fine so far. (OK, maybe using iterator and iteration variable is a bad idea, but that’s the free-time code, right? 🙂 ).

$ clang++ -std=c++11 a.cpp; ./a.exe
expectedSize = 100
data.size() = 0
data.capacity() = 100

data[2891] = 32768

…And the problem is direct memory access. Vector is told to reserve memory, but not to resize itself (compare std::vector::reserve vs std::vector::resize). In my case OpenGL got a buffer of size 0 and crashed.

The solution is quite simple: either to resize vector and use array access braces or reserve memory and push_back data.

Surprisingly, iterator incrementation worked fine in this example, also for “indexes” outside vector. I also made a simple test and in my implementation (clang++ 3.9 x86_64-w64-windows-gnu). Vector as above after reserving 100 fields returned (random) number for first 2892 fields.

Would you spot it at first sight? 😉

4 thoughts on “Watch out for std::vector size

  1. Not to toot my own horn, but the error seemed obvious to me, to be honest (in fact, it was jarring to read `*it = t; it++` after `reserve`).

    That being said, the distinction between reserve/resize is good to know about and I can see how the presented code may be confusing for one less familiar with the language. So, good job.

    By the way, a few suggestions:
    – I prefer `v.data()` to `&v[0]`, though the semantics are nearly the same
    – you could use `reserve` + `back_inserter` + `generate_n` or `resize` + `generate` to avoid this whole mess 😉

  2. The problem boils down to a difference between “reserve” and “resize”. I think that now you won’t make this mistake again 🙂 Good that you wrote about it. Also, I second sugestions by KrzaQ.

Leave a Reply

Your email address will not be published. Required fields are marked *