Segmentation fault calling insert on vector

E

Eric Lilja

Consider the following code:
#include <iostream>
#include <string>
#include <vector>

using namespace std;

int
main()
{
vector<string> wl;

vector<string>::iterator it = wl.begin();
string w;

while(cin >> w)
{
wl.insert(it++, w);
cout << "inserted successfully" << endl;
}
}

It crashes after one succesful insert it seems. I know I can solve it
using push_back or push_front, but I'm looking at a bigger program that
uses inserts exclusively and doesn't crash...In the real program I dont
want to add elements to the front or the back
 
V

Victor Bazarov

Eric said:
Consider the following code:
#include <iostream>
#include <string>
#include <vector>

using namespace std;

int
main()
{
vector<string> wl;

vector<string>::iterator it = wl.begin();
string w;

while(cin >> w)
{
wl.insert(it++, w);
cout << "inserted successfully" << endl;
}
}

It crashes after one succesful insert it seems. I know I can solve it
using push_back or push_front, but I'm looking at a bigger program
that uses inserts exclusively and doesn't crash...In the real program
I dont want to add elements to the front or the back

'it' is most likely invalid after you insert. If you try using it (and
incrementing constitutes using), you get undefined behaviour.

You probably meant

it = wl.insert(it, w); ++it;

Here, 'it' returned from 'insert' is the iterator to the newly inserted
element. If you need the next one, increment it.

V
 
T

Thomas Tutone

Eric said:
Consider the following code:
#include <iostream>
#include <string>
#include <vector>

using namespace std;

int
main()
{
vector<string> wl;

vector<string>::iterator it = wl.begin();
string w;

while(cin >> w)
{
wl.insert(it++, w);
cout << "inserted successfully" << endl;
}
}

It crashes after one succesful insert it seems. I know I can solve it
using push_back or push_front, but I'm looking at a bigger program that
uses inserts exclusively and doesn't crash...In the real program I dont
want to add elements to the front or the back

Two problems. First, std::vector::insert() invalidates all interators,
but returns a valid iterator. That means if you continue to use the
old iterator - as you do - you are invoking undefined behavior - in
this case, a crash. Second, as a conceptual matter,
std::vector::insert() inserts BEFORE the iterator. You set the
iterator to begin(), so conceptually this is wrong (because you don't
want to insert BEFORE begin()), even though this will work in practice
(because for an empty vector, begin()==end()).

So, I would change your program as follows:

int main()
{
vector<string> wl;
vector<string>::iterator it = wl.end();
// note change in above line
string w;
while(cin >> w) {
it = wl.insert(it, w);
// note change in above line
cout << "inserted successfully" << endl;
}
}


Best regards,

Tom
 
E

Eric Lilja

Victor said:
'it' is most likely invalid after you insert. If you try using it (and
incrementing constitutes using), you get undefined behaviour.

You probably meant

it = wl.insert(it, w); ++it;

Right! I forgot that insert() returns a valid iterator! It worked in
the larger program because in that one a separate function was called
for each insert() that obtained a fresh iterator for each time it was
called. Thanks for the quick reply.
Here, 'it' returned from 'insert' is the iterator to the newly inserted
element. If you need the next one, increment it.

V

Eric
 
V

Victor Bazarov

Thomas said:
[..] First, std::vector::insert() invalidates all
interators, [..]

Actually, 'insert' only invalidates iterators if reallocation
happens. You can prevent that by using 'reserve'.

V
 
T

Thomas Tutone

Victor said:
Thomas said:
[..] First, std::vector::insert() invalidates all
interators, [..]

Actually, 'insert' only invalidates iterators if reallocation
happens. You can prevent that by using 'reserve'.

Now, I know that generally when one argues with Victor Bazarov in the
context of C++, chances are high that one is wrong and Victor is right.
But I think in this case, you are partially incorrect. (And I think
my answer was partially incorrect as well.)

I said that insert invalidates all interators. You said that insert
invalidates iterators _only_ if reallocation happens. I don't have my
copy of Josuttis (or the Standard) handy, but both Dinkumware and SGI
state:

"If no reallocation occurs, iterators become invalid only from the
point of insertion through the end of the sequence."

Thus, I think it is accurate that some - but not all - iterators do
become invalid. In the OP's example, he continues to use the iterator,
which is at the point of insertion. I believe that iterator is
invalid, regardless of whether reallocation occurs.

So - I acknowldege that my statement that _all_ iterators are
invalidated was overbroad. But I think your correction was similarly
inaccurate. Please correct me if I've misunderstood.

Best regards,

Tom
 
V

Victor Bazarov

Thomas said:
Victor said:
Thomas said:
[..] First, std::vector::insert() invalidates all
interators, [..]

Actually, 'insert' only invalidates iterators if reallocation
happens. You can prevent that by using 'reserve'.

[..]
I said that insert invalidates all interators. You said that insert
invalidates iterators _only_ if reallocation happens. I don't have my
copy of Josuttis (or the Standard) handy, but both Dinkumware and SGI
state:

"If no reallocation occurs, iterators become invalid only from the
point of insertion through the end of the sequence."
[..]

The Standard says that iterators before the point of insertion remain
valid if no reallocation occurs. You're right, some do become invalid.
In practice they probably simply point to different elements. But who
cares about what's in practice? :)

V
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top