views:

72

answers:

3

I have this bit of code:

cerr << client->inventory.getMisc().front()->getName() << endl;
vector<itemPtr>::iterator it;
it = client->inventory.getMisc().begin();
cerr << (*it)->getName() << endl;

Let me explain that a bit:

client is a tr1::shared_ptr that points to an object that has a member named inventory that has a private vector<itemPtr> member accessible by getMisc(). itemPtr is a typedef for tr1::shared_ptr<Item>, and getName() returns a private std::string member of Item.

Essentially, client->inventory.getMisc() boils down to a std::vector, and I'm trying to get an iterator to its first element.

The problem is that the fourth line segfaults. Apparently either the iterator or the shared_ptr it points to is invalid. I used the first cerr statement to test if the vector itself was valid, and it prints as it should, so I think it is.

Is there anything I'm doing wrong? Alternatively, what would you guys do to debug this?

+1  A: 

what would you guys do to debug this?

Step though the code to see what's different about what front() returns and what (*it) returns.

Michael Burr
I've tried this, but I can't inspect the variables well with gdb. When I try `p client->inventory.getMisc().front()`, gdb says 'There is no member or method named inventory'. When I try `p *it`, I see it holds a `shared_ptr<Item>`. When I try `p **it`, gdb says 'One of the arguments you tried to pass to operator* could not be converted to what the function wants'.
Max
+11  A: 

Exactly what is the signature of getMisc?

If you're actually returning a std::vector<itemPtr> then you are returning a copy of the list. In that case, the first access pattern will work (slowly) because the temporary copy doesn't get destroyed until after front finishes executing, by which time the itemPtr itself is copied into a temporary. The second fails because after getting at the iterator with begin, the temporary falls out of scope and is destroyed, leaving the just-created iterator hanging.

Walter Mundt
I'm guessing that this is a nice bit of psychic debugging.
Michael Burr
@Walter: Nice catch.
Steven Sudit
Yeah, that's what it returns. What should I do instead, return a reference?
Max
Fixed the problem. I put the vector manipulation in a member function of `inventory`, which I probably should've done to begin with. Thanks for your help.
Max
+1 for psychic debugging ;)
Evan Teran
Thanks all. @Max: You can return a (possibly const) reference, or even store the vector itself internally in a shared_ptr and return that, but keeping the vector private works great.
Walter Mundt
A: 

Are you sure that the vector isn't empty? It's possible that front and begin behave slightly differently and front could work by pure chance, while additional checks in the iterator itself cause the seg fault when it's used.

Mark B