I have a class Actor. I am trying to sort an std::vector<Actor*>. During this sort I get a segmentation violation, apparently when one of the elements in my vector suddenly points to something totally different. I will try to post all the relevant code:
// Creation and filling of my vector
static std::vector<Actor*> buyers;
buyers.clear();
// allActors is a static std::vector<Actor*>
for (unsigned int i = 0; i < allActors.size(); i++) {
allActors->myDeals[resource].clear();
int price = allActors->myPrices[resource];
if (price == 0) continue; // Not trading in this good.
else if ((price < 0) && (allActors->myResources[resource] > 0)) sellers.push_back(allActors);
else {
buyers.push_back(allActors);
log("Added allActors " + stringify(i) + " " + stringify(allActors));
}
}
log("doTrade " + stringify(resource) + " Line 1");
if (buyers.size() == 0) return;
// Sort by price.
tradeResource = resource;
// Static vector for debugging purposes
theSorts = &buyers
std::sort(buyers.begin(), buyers.end(), ActorDescendingSorter());
The ActorDescendingSorter is just a functor for sorting Actor*:
struct ActorDescendingSorter {
// Comparator to sort Actor pointers by price, from highest to lowest, for a resource.
inline bool operator() (Actor* a1, Actor* a2) {
// Note negation! This is so sort will return a list from highest to lowest.
checkActors();
std::cout << (int) a1 << " " << (int) a2 << std::endl;
return (!((*a1) < (*a2)));
}
};
You will note that it now contains some debugging code. checkActors is just a static method to print out the contents of the list being sorted:
void Actor::checkActors () {
for (std::vector<Actor*>::iterator i = theSorts->begin(); i < theSorts->end(); ++i) {
std::cout << "Checking : " << (*i) << " " << (int)(*i) << std::endl;
}
}
You should note that Actor overwrites the << operator to print out its name, and I like printing addresses as ints.
Now finally, we can look at the output:
164240728 164231640
Checking : London Cloth 164228968
Checking : London 1 164231640
Checking : London 2 164231904
Checking : London 3 164232168
Checking : Kent 1 164232432
Checking : Sussex 1 164232696
Checking : Sussex 2 164232960
Checking : Wessex 1 164233224
Checking : Wessex 2 164233488
Checking : Essex 1 164233752
Checking : Essex 2 164234016
Checking : Bergen 1 164234280
Checking : Bergen 2 164234544
Checking : Trondhjem 164239936
Checking : Nordland 164240200
Checking : Ostlandet 164240464
Checking : Stavanger 164240728
164240728 164228968
Checking : London Cloth 164228968
Checking : London 1 164231640
Checking : London 2 164231904
Checking : London 3 164232168
Checking : Kent 1 164232432
Checking : Sussex 1 164232696
Checking : Sussex 2 164232960
Checking : Wessex 1 164233224
Checking : Wessex 2 164233488
Checking : Essex 1 164233752
Checking : Essex 2 164234016
Checking : Bergen 1 164234280
Checking : Bergen 2 164234544
Checking : Trondhjem 164239936
Checking : Nordland 164240200
Checking : Ostlandet 164240464
Checking : Stavanger 164240728
164240728 5433
Segmentation fault
So clearly, what's going on is that the sorter is going happily along, comparing Actor pointers. (Actually they are subclasses, Actor being abstract.) Then it comes to the point where it tries to compare the Actor named Stavanger to something totally random, and weirdness results.
I should mention that this behaviour disappears if I have fewer Actor objects. Remove just one, and it works! More accurately, remove just one of the ones that go into the list to be sorted. The magic number appears to be 17. I'm puzzled and confused. Help me?
To win one hundred victories in one hundred battles is not the acme of skill. To subdue the enemy without fighting is the acme of skill.