2
votes

My program crashes on this line but only in debug build, it works fine in release build.

m_lstIds.insert(m_lstIds.begin() + indexInsert, ID);

'm_lstIds' is a std::vector of int, 'ID' is an int. When the program crashed, m_lstIds had 3 items (1, 2, 3). indexInsert was '0' and ID was '0'.

The error message says:

Expression: vector iterator + offset out of range

I am running visual studio 2010; I am guessing it has something to do with bad project settings which conflicted with STL optimization.

Edit: When I said: "works on release" I meant if I do std::cout<<m_lstIds[i] for i = 0..3, I will actually get 0,1,2,3 printed out. In debug build it just crashes when I try to insert.

Edit2: I found the answer! Thanks everyone for the help.

Here is the shortest repro. The problem is the memset function I call at the constructor. Because the constructor of m_lstItem was called before the memset, it will erase whatever data in the vector that allowed insert to work properly.

What's really interesting is how this worked in release but not in debug. Would be great if someone can explain that part.

struct SimpleList
{
  SimpleList()
  {
    memset(this, 0, sizeof(SimpleList));
    m_lstItem.push_back(0);
    m_lstItem.push_back(1);
    m_lstItem.push_back(2);
  }

  void Crash()
  {
    m_lstItem.insert(m_lstItem.begin() + 0, 3);
  }

  std::vector<int>m_lstItem;
};

int main(int argc, char** argv[])
{ 
  SimpleList sl;
  sl.Crash();
  return 0;
}
2
Are you really sure that the container has three elements and that the index was 0? The fact that it "works" in release implies that the code is actually broken, but without the runtime checks you don't get any errors. - James McNellis
Show us a working example of your code, it's tough for us to figure out how the vector is modified, used, etc. - wkl
I can't reproduce the problem. Will need to see the full code. - Benjamin Lindley
I believe you're not initializing a variable which is set to 0 in the release version and 0xcdcdcdcd in the debug version or some other garbage, which ends up referencing an invalid index. This would be possible if you don't initialize the "i" variable properly (with a 0). Ahh no, sorry, you said at insert.. well you could check those too :) - Pablo Ariel
memset(this, 0, sizeof(SimpleList)); DON'T do this unless your class is POD !! std::vector MUST be initialized with its own constructor. - fefe

2 Answers

4
votes

memset(this, 0, sizeof(SimpleList)); is unsafe when your struct is not a POD.

Due to the member std::vector<int>m_lstItem;, your struct is not a POD.

Therefor, using memset is unsafe in this case, and leads to undefined behaviour. In other words: anything is allowed to happen! And anything includes working as expected...

My advice: Do not use memset in C++ unless you totally know what you are doing.

0
votes

I guess the indexInsert is not 0 when the programe running. And the vector will throw exception when the vector out of range in DEBUG mode,and in RELEASE mode it won't. So show you full code.