is there anybody using BWAPI who gets access violation error when accessing the Unit objects of the current game?
i am certain that the error is not in my code.. anyway.. is there anything i can do to avoid access violation?
i am getting this error sometimes at line with the comment bellow.. this code bellow execute many times and only sometimes i get the error..
int Squad::getSize() {
int no = 0;
for (int i = 0; i < (int) agents.size(); i++) {
BaseAgent* agent = agents.at(i);
if (agent != NULL && agent->isAlive() && agent->getUnit() != NULL && !agent->getUnit()->isBeingConstructed()) // this line
no++;
}
return no;
}
this is the code that I use to remove an BaseAgent from the vector.. analyze that and see if i can do it better:
void AgentManager::cleanup() {
//Step 2. Do the cleanup.
int cnt = 0;
int oldSize = (int)agents.size();
for (int i = 0; i < (int)agents.size(); i++) {
if (!agents.at(i)->isAlive()) {
delete agents.at(i);
agents.erase(agents.begin() + i);
cnt++;
i--;
}
}
int newSize = (int)agents.size();
}
the BaseAgent code is on this link
I would speculate that this line:
BaseAgent* agent = agents.at(i);
is returning some invalid pointer which is not set to 0.
Looking at your cleanup code, it looks a bit complicated. I would suggest
looping over the entire vector, deleting the dead elements and
setting the pointers to 0.
After the loop, use the erase-remove idiom to remove all NULL pointers from the vector.
step 1
for (unsigned int i = 0; i < agents.size(); ++i) {
if (!agents.at(i)->isAlive()) {
delete agents.at(i);
agents.at(i) = 0;
}
step 2
agents.erase(std::remove(agents.begin(), agents.end(), 0), agents.end());
Related
The int winner should be set to 2 under certain conditions but it's somehow being set to a variety of higher values, most commonly 6. I have no idea how this is happening, as there is no other function in my class that affects winner, and the variable isn't even mentioned anywhere else in the program. What is most confusing to me is that I have an almost identical function (P2Move()) that is literally identical in how it sets the winner variable to P1Move(), and that function runs perfectly.
Some info: The class this is part of is called Board, which acts as a checkerboard array made up of Square class objects.
Below is the function causing the problem. Near the bottom, the statement else if((canTake.size()==0)&&(canMove.size()==0)) {Board::winner = 2;} causes the problem. Everything else seems to work when I remove the problematic part from the function, but I need that part to work in order to submit the final project.
void Board::P1Move()
{
P1pieces = 0;
std::vector <Move> canMove;
std::vector <Move> canTake;
for(int j = 0; j < bSize; j++)
{ //Start of j loop.
for(int i = 0; i < bSize; i++)
{ //Start of i loop.
Square sq = board[i][j];
bool cTakeL = canTakeL(i,j);
bool cTakeR = canTakeR(i,j);
bool cMoveL = canMoveL(i,j);
bool cMoveR = canMoveR(i,j);
if(board[i][j].getPl() == P1)
{
P1pieces++;
if(cTakeL)
{
Move a = Move(sq.getIndex(),board[i-2][j+2].getIndex(),board[i-1][j+1].getIndex(),0);
canTake.push_back(a);
}
if(cTakeR)
{
Move b = Move(sq.getIndex(),board[i+2][j+2].getIndex(),board[i+1][j+1].getIndex(),0);
canTake.push_back(b);
}
if(cMoveL)
{
Move c = Move(sq.getIndex(),board[i-1][j+1].getIndex(),0,0);
canMove.push_back(c);
}
if(cMoveR)
{
Move d = Move(sq.getIndex(),board[i+1][j+1].getIndex(),0,0);
setWinner(d.getSpos());
canMove.push_back(d);
}
}
} //End of i loop.
} //End of j loop.
if(canTake.size()!=0)
{
time_t t;
time(&t);
srand(t);
int moveNum = rand()%canTake.size();
std::string output = "p1 ";
Move out = canTake.at(moveNum);
int i = 0;
int j = 0;
for(int y = 0; y < bSize; y++)
{
for(int x = 0; x < bSize; x++)
{
if(board[x][y].getIndex()==out.getSpos())
{
i = x;
j = y;
}
}
}
if(board[i-2][j+2].getIndex()==out.getEndPos())
{
board[i-2][j+2].setOcc(true);
board[i-2][j+2].setPl(P1);
board[i-1][j+1].setOcc(false);
board[i-1][j+1].setPl(NA);
}
else if(board[i+2][j+2].getIndex()==out.getEndPos())
{
board[i+2][j+2].setOcc(true);
board[i+2][j+2].setPl(P1);
board[i+1][j+1].setOcc(false);
board[i+1][j+1].setPl(NA);
}
output = output + out.toString();
setCmove(output);
board[i][j].setOcc(false);
board[i][j].setPl(NA);
}
else if(canMove.size()!=0)
{
time_t t;
time(&t);
srand(t);
int moveNum = rand()%canMove.size();
std::string output = "p1 ";
Move out = canMove.at(moveNum);
int i = 0;
int j = 0;
for(int y = 0; y < bSize; y++)
{
for(int x = 0; x < bSize; x++)
{
if(board[x][y].getIndex()==out.getSpos())
{
i = x;
j = y;
}
}
}
if(board[i-1][j+1].getIndex()==out.getEndPos())
{
board[i-1][j+1].setOcc(true);
board[i-1][j+1].setPl(P1);
}
else if(board[i+1][j+1].getIndex()==out.getEndPos())
{
board[i+1][j+1].setOcc(true);
board[i+1][j+1].setPl(P1);
}
output = output + out.toString();
setCmove(output);
board[i][j].setOcc(false);
board[i][j].setPl(NA);
}
else if((canTake.size()==0)&&(canMove.size()==0))
{
Board::winner = 2;
}
P1pieces = canTake.size() + canMove.size();
}
You are working with std::vector, which is a good thing. (Too much beginner "C++" code uses C arrays.) The vector class template allows for a pretty easy way to find out if and where you might have an out-of-bounds access (as suggested in the comments):
Instead of accessing vector elements using operator[], change your code to use the .at() member function. .at() is bounds-checking, and will throw an exception if you access out-of-bounds (instead of silently breaking your program).
In production code, operator[] is usually preferred as omitting the bounds check is more efficient. But while learning, .at() can help you quite a bit.
Also, getting in the habit of using code checkers like valgrind or the assert macro to check your assumptions is a good thing, even when you got past the point where you wouldn't use .at() anymore.
I'm trying to "erase" an element from a vector that is itself contained in another vector. However, either I forgot how to do this, I missed the point, or there's a huge oversight. It always erases the very first element in the vector, whatever I try.
void release_docking() {
int loop_R = (int)parent_cell->cells.size();
for (int i = 0; i < loop_R; i++) {
int loop_C = (int)parent_cell->cells[i].size();
for (int j = 0; j < loop_C; j++) {
if (parent_cell->cells[i][j] = this) {
parent_cell->cells[i].erase(parent_cell->cells[i].begin() + j);
if (parent_cell->cells[i].empty()) {
parent_cell->cells.erase(parent_cell->cells.begin() + i);
}
parent_cell = nullptr;
is.docked = false;
resize_cells(root_cell);
break;
}
}
}
}
This line
if (parent_cell->cells[i][j] = this) {
will assign this to parent_cell->cells[i][j] and evaluate to true.
After that it will be erased.
That should be == not =.
Recent compilers should warn you about this. Make sure that warnings are turned on.
This is a bit code i'm having trouble with:
int pressedKey = event.getNativeKeyCode();
for (int i=0; i <= AllTriggerPads.size() ;i++) {
if (AllTriggerPads[i]->get_key() == pressedKey){
AllTriggerPads[i]->mBufferPlayerNode->start();
}
}
the get_key() is getting a EXC_BAD_ACCESS (Code=1, ...) Error.
I seem to have a referencing problem. I am using almost the same code in the mouseDown and the fileDrop function:
for (int i=0; i < AllTriggerPads.size() ; i++) {
if (AllTriggerPads[i]->mRect.contains(event.getPos())) {
AllTriggerPads[i]->mBufferPlayerNode->start();
}
}
This works fine!
Sooooo, i guess i am using the AllTriggerPads vector (of obj pointers) not correctly. So I CAN use AllTriggerPads[i]->mRect.contains(event.getPos())
but I CANT use AllTriggerPads[i]->get_key(). And I CANT access the value itself by AllTriggerPads[i]->key
I have tried it with AllTriggerPads.at(i) but then i get an out of range error which makes me wonder even more.
The AlltriggerPads was initialized with
vector<TriggerPad*> AllTriggerPads;
So how can I access the key member?
You are having an off-by-one error.
for (int i=0; i <= AllTriggerPads.size() ;i++)
replace with
for (int i=0; i < AllTriggerPads.size(); ++i)
(The ++ thing is irrelevant, it's just better practice to always use pre-increment)
You are trying to access an array element which doesn't exist. That's why it throws EXC_BAD_ACCESS. Change the for loop conditional to
for (int i = 0; i < AllTriggerPads.size(); ++i) {
if (AllTriggerPads[i]->get_key() == pressedKey) {
AllTriggerPads[i]->mBufferPlayerNode->start();
}
}
or if C++11 support is enabled, simplify it to
for (auto i : AllTriggerPads) {
if (i->get_key() == pressedKey) {
i->mBufferPlayerNode->start();
}
}
I'm having some troubles adding and removing elements from an std::vector (population, in the example code). What I want to do is to erase an element if a condition is satisfied and copy the element if instead other conditions are satisfied. Here's the code:
for( int i = 0; i < walkers_num; i++) {
if( population[i].molteplicity == 0 ) {
population[i] = population.back();
population.pop_back();
i--;
} else {
for( int j = population[i].molteplicity; j > 1; j-- ) {
population.push_back(population[i]);
}
}
}
walkers_num = population.size();
What I get is:
*** error for object 0x7f86a1404498: incorrect checksum for freed object - object was probably modified after being freed.
I guess I'm using some std::vector property in a wrong way, since a very similar algorithm (conceptually they seem identical to me) seems to work if population is instead an std::list:
list<Walker>::iterator it;
list<Walker>::iterator end = thread_population[i].end();
for ( it = thread_population[i].begin(); it != end; ) {
if( it->molteplicity == 0 ) {
it = thread_population[i].erase(it);
continue;
}
for( int j = it->molteplicity; j > 1; j-- ) {
population.push_back(*it);
}
++it;
}
walkers_num = population.size();
Can you help me?
You haven't posted quite enough code.
I'm assuming you omitted at the start of the fragment:
walkers_num = population.size();
And are trying to visit the whole array. In that case try:
walkers_num = population.size();
for( int i = 0; i < walkers_num; i++) {
if( population[i].molteplicity == 0 ) {
population[i] = population.back();
population.pop_back();
i--;
--walkers_num; //Array has been shortened.
}
//....
You seem to have realised the length has changed because you put walkers_num = population.size(); at the end. You need to keep track throughout.
There are subtle reasons why your iterator code is likely to work but technically just as invalid. You're not allowed to assume end is valid after a modification.
After spending an entire day debugging, I've noticed that memory leaks always occur when the following function is called:
void merge(TContainer<T> List2)
{
TContainer<T> temp(this->Size);
for (int i = 0; i < this->Size; i++)
{
temp.Interface[i] = this->Interface[i];
}
this->Interface = new T[Size + List2.size()];
Size = Size + List2.size();
for(int i = 0; i < List2.size(); i++)
{
Interface[i] = List2[i];
}
for(int i = List2.size(); i < Size; i++)
{
Interface[i] = temp[i];
};
delete[] temp.Interface;
}
Within the code:
TContainer_Short<unsigned short> Temp = TContainer_Short<unsigned short>(0);
for(int i = (ToUpdate.size() - 1); i >= 0; i--)
{
UpdateInUse = true;
ToUpdate[i].Ad.push_back(AdQueue[i].Indirect[0].Address);
auto Entity = ToUpdate[i];
UpdateInUse = false;
float HighestScore = 0;
int Index = 0;
//Go through all the advertisements on their queue
//Make sure our last index is always the next plot point in our story.
for(int j = 0; j < ToUpdate[i].Ad.size(); j++)
{
AdvertisementBase Ad = *World::get()->getTemplateAd(Entity.Ad[j]);
float temp = returnScore(Entity.Index, Ad);
//If its higher than our current score, set i to this index
if(temp > HighestScore)
Index = j;
}
//Index is last pos when we're currently continuing our plot queue. We haven't changed our mind about what advertisement we want
if(Index !=(Entity.Ad.size() - 1))
{
AdvertisementBase *Ad = World::get()->getTemplateAd(Entity.Ad[Index]);
this->reduceAdChain(Entity.Index, Ad);
}
else
{
//Makes sure that the entity is on track for the next goal that it had already determined
plan(Entity.Index,AdQueue.Interface[Entity.Index].Indirect[0].Address);
}
Temp.push_back(Entity.Index);
ToUpdate.pop_back();
}
if(!ExecutingInUse)
{
ExecutingInUse = true;
Executing.merge(Temp);
ExecutingInUse = false;
}
delete[] Temp.Interface;
}
However, I can't seem to figure out why it only occurs when there are multiple threads. The array itself is only ever being referenced by one thread at a time, (Atomic), so it shouldn't be a problem.
Deleting the Executing::merge reference makes the memory leak go away, and definitely speeds up performance noticeably in single threaded scenarios.
The thing that’s even more odd is that merge is used in other places:
void reduceAdChain(unsigned short Index, TContainer<AdvertisementReference> Ads)
{
AdQueue[Index].Indirect.merge(Ads);
}
And no memory leak gets created, even though reduceAdChain is called almost a full magnitude more often than Executing::merge. And removing merge in this area, creates no noticeable performance increase, even though
A) The arrays being taken in by reduceAdChain for the merge are almost 3x the size on average than the arrays that pass into Executing::merge
and
B) The overall length of reduceAdChain is almost 5x the length of Executing.
However, executing does get cleared at the end of every iteration.
This is one of the weirdest things I've ever ran into in multithreaded environments.
Where Executing gets used:
if(!m_simulated_entities[i]->ExecutingInUse)
{
for (int j = 0; j < m_simulated_entities[i]->Executing.size(); )
{
// Retrieve Tag Data and Update Constants
m_simulated_entities[i]->ExecutingInUse = true;
ExecutingIndex = m_simulated_entities[i]->Executing[j];
m_simulated_entities[i]->ExecutingInUse = false;
TagIndex = m_simulated_entities[i]->TagIndicesPerEntity[ExecutingIndex];
now = std::chrono::system_clock::now();
time_now = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()).count();
if (m_simulated_entities[i]->Timing[m_simulated_entities[i]->Executing[j]].TimeConstant == 0)
{
//Make sure all of our new attribute values still allow this entity to live
if(!m_simulated_entities[i]->updateTick(ExecutingIndex))
m_simulated_entities[i]->removeInstance(ExecutingIndex);
else
{
//Compute our new transfer constant
m_simulated_entities[i]->prepare(ExecutingIndex);
//Update the tagging system
m_simulated_entities[i]->updateTags(ExecutingIndex);
//Search for new decisions
m_simulated_entities[i]->ToSearch.push_back(ExecutingIndex);
}
//Remove the index from execution
m_simulated_entities[i]->ExecutingInUse = true;
m_simulated_entities[i]->Executing.Remove(j);
m_simulated_entities[i]->ExecutingInUse = false;
}
else if (time_now - m_simulated_entities[i]->Timing[ExecutingIndex].LastUpdateTime > updateConstants[TagIndex])
{
m_simulated_entities[i]->Timing[ExecutingIndex].TimeConstant--;
m_simulated_entities[i]->Timing[ExecutingIndex].LastUpdateTime = time_now;
j++;
}
}
}
For the test, updateTick is disabled and will always return true, since allowing that function to properly execute would have made finding the memory leak a lot harder.
in the function merge:
this->Interface = new T[Size + List2.size()];
You should check if the pointer this->Interface is NULL or not, if it is not, it should be freed first. Otherwise if the function merge is called multiple times, it will leak.
So the code will be:
if (this->Interface != NULL)
delete[] this->Interface;
this->Interface = new T[Size + List2.size()];
Sorry for possibly stupid question: if you have vectors as "ToUpdate[i].Ad" etc, why don't you use "this->Interface" as vector too? This could save you a lot of time hunting this leak.