Sign in to follow this  
King of Men

Memory overruns with std::vector?

Recommended Posts

At least, that's all I can think of. I am working on some economics code, and I have a class which needs to keep track of several possible sources for each of several possible resources. It therefore contains this:
std::vector<std::vector<Deal*> > myDeals;
(...)
myDeals.reserve(Resource::numResources);
where Deal is a helper struct containing the seller, the price, and the amount on offer. Now, at one point my buyer class goes through a list of all possible sellers, storing those that it has access to and can afford to buy from at the current price. It also registers that deal with the seller. So, now I come to testing this code. I have two buyers, which are referred to as 'ProvinceA' and 'ProvinceB'. They want to buy labour, for which there are two sellers, 'PopA' and 'PopB'. ProvinceA goes first, and registers first with PopA, increasing the size() of PopA's myDeals[labourIndex] to 1. That's just as it should be. Then it tries to register with PopB, and Something Weird happens. Here is the code for registering with a seller:
void Actor::registerBid (unsigned int res, Deal* d) {
  assert(d);
  log(stringify(this) + " Line a of registerBid; tester size " + stringify(tester-&gt;myDeals[res].size()));
  myDeals[res].push_back(d);
  log(stringify(this) + " Line b of registerBid; tester size " + stringify(tester-&gt;myDeals[res].size()));
}

Some debugging included, as you'll note. Here 'tester' is a global pointer to PopA. Now here is the output: PopB Line a of registerBid; tester size 1 PopB Line b of registerBid; tester size 4294966313 So, the code arrives in registerBid and finds that PopA has one deal registered, just as it should be. It pushes the new Deal onto PopB's vector - and suddenly calling PopA's vector's size() method gives nonsensical results. It seems to me that this is a symptom of a buffer overrun or something similar - at any rate it seems clear that PopA->myDeals[res] has got clobbered - but I don't understand how that can happen with this code. Is there some pitfall involved with using vectors of vectors? Not sure if it's relevant, but I'm using gcc 3.2.3 on Linux24SL3.

Share this post


Link to post
Share on other sites
Before examining your code further, let me ask this:
myDeals[res].push_back(d);
Are you sure that res < myDeals.size()? If not, you might consider using at() instead of operator[](), as it will throw an exception (IIRC) if the index is out of range.

My thought here (which might be totally off base), is that where you have:
myDeals.reserve(Resource::numResources);
You actually mean:
myDeals.resize(Resource::numResources);
resize() and reserve() are often confused with one another, but they do fundamentally different things.

[So very slow...]

Share this post


Link to post
Share on other sites
Log/assert:
myDeals.size()
and
myDeals.size() > res

researve builds space of non-initialized data.

resize both reserves and initializes the data.

You reserve if and only if you don't want to initialize the data now, and can get around to doing it later, and you know how much data you will have, and you would rather spend the time reallocating once now then doing it "on the fly" later.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this