Accessing an object from a vector of object pointers - c++

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();
}
}

Related

Declaring and using custom-class vectors

My mate and I have just come accross a problem we couldn't manage to solve just yet.
We have two classes, solution and generation.
solution has a lot of attributes, and generation has, among others, a vector<solution> pool attribute.
The generation class has a generatePool function :
void generation::generatePool(int initsize){
for(int i = 0; i < initsize; i++){
printf("%d\n", i);
pool.push_back(get_randomized_solution(args));
}
}
in which get_randomized_solution itself returns a solution. Problem is, the program compiles but crashes (Segmentation fault) at the push_backline
We've already tried resize and reserve on the pool vector, we also tried using pointers... but it still crashes and now google (and SO) seemingly have gone out of ideas to help us. We've also redefined solution& solution::operator=(const solution&) and a solution::solution() (with no arguments) constructor, which basically returns an empty solution. Where do you think the problem comes from ?
EDIT:
Here's the get_randomized_solution method:
solution get_randomized_solution(int size, int rcap, int rcom, bool randomized){
solution sol = solution(size, rcap, rcom);
vector< pair<int,int> > cibles;
for(int i = 0; i < size; i++){
for(int j = (i==0) ? 1 : 0; j < size; j++){
cibles.push_back(make_pair(i, j));
}
}
srand(rand());
if(randomized) random_shuffle(cibles.begin(), cibles.end());
for(int k = 0; k < cibles.size(); k++){
if(sol.removeCaptor(cibles[k])){
if(!sol.realisable()){
sol.addCaptor(cibles[k]);
}
}
}
return sol;
}
More complete code: https://codeshare.io/2jLnzB
Well that was indeed get_random_solution, in which there was a size = size line which caused the bug. Really sorry for useless posting.

C++ Error C2100: Illegal Indirection--bubbleSort

I am trying to send a vector into a bubbleSort function to organize numbers from max to min as they are produced one by one, but I am getting the "C2100: Illegal indirection" warning. Can someone please help me out?
private: void bubbleSort(vector<int> &matrixPtr)
{
int temp;
int numLength = *matrixPtr.size( );//length of vector
for (int i = 1; (i <= numLength);i++)
{
for (int j=0; j < (numLength -1); j++)
{
if (*matrixPtr[j+1] > *matrixPtr[j])
{
temp = *matrixPtr[j];//Swap elements
*matrixPtr[j] = *matrixPtr[j+1];
*matrixPtr[j+1] = temp;
}
}
}
}
The bubbleSort is drawn from another function ahead of it:
bubbleSort(&output);//pass to bubble sort
for (int rows=0;rows<creation->getZeroRows();rows++)
{
for (int cols=0;cols<creation->getCols();cols++)
{
txt_DisplayRowSum->Text= String::Concat(txt_DisplayRowSum->Text, (*creation->zeroArrayPtr)[rows][cols]," ");
}
txt_DisplayRowSum->Text+=" \n";
}
Thank you for your help in advance
You are incorrectly using references.
Instead of *matrixPtr.size( ) you need matrixPtr.size(), and everywhere else in the function you do not need the * when referring to matrixPtr. Also, when passing the vector to the function, you should pass just output and not &output.
You should not and can not use references like pointers. While similar, they're different in several important ways. I also recommend this question for a good summary of those differences.

c++ BWAPI exception access violation

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());

vector.push_back() crashes

I have a problem while working with vectors of a class. I have tried whittling away at the code as much as possible, leaving me with the code below. Yet, after doing this, I still cannot figure out why my program is crashing. I come from a world of VBA and my C++ debugging skills are poor to say the least and I apologize for that up front. Any guidance to improve my ability here will be gladly accepted.
My class:
class Tester {
public:
int varA;
int varB;
Tester() {
varA = 1;
varB = 1;
}
Tester(Tester& P1, Tester& P2) {
varA = P1.varA + P2.varA;
varB = P1.varB + P2.varB;
}
Tester(const Tester &Source) {
varA = Source.varA;
varB = Source.varB;
}
};
My test mains:
Does not work:
int main() {
std::vector < Tester > BreakIt;
for (int i = 0; i < 2500; i++) {
Tester newTester;
BreakIt.push_back(newTester);
Tester& tempTester = BreakIt.at(0);
for (int j = 0; j < 4; j++) {
BreakIt.push_back(Tester(newTester, tempTester)); //This is where it crashes.
}
}
return 0;
}
Does work:
int main() {
std::vector < Tester > BreakIt;
Tester newTester;
BreakIt.push_back(newTester);
for (int i = 0; i < 2500; i++) {
Tester& tempTester = BreakIt.at(0);
for (int j = 0; j < 4; j++) {
BreakIt.push_back(Tester(newTester, tempTester));
}
}
return 0;
}
Does work:
int main() {
std::vector < Tester > BreakIt;
for (int i = 0; i < 2500; i++) {
Tester newTester;
BreakIt.push_back(newTester);
Tester& tempTester = BreakIt.at(0);
}
return 0;
}
The push_back() line that breaks does run a few times before the crash. It seems that when I change certain things around and recompile, the point at which it crashes changes (i.e. 20 times through the main loop vs. 175 times vs. 1000 times). However, once I've compiled, it will typically run through the the same iteration each time before crashing.
I suspect that this is some kind of 'undefined behavior' but from where I'm not sure.
Can someone please help me identify why BreakIt.push_back(Tester(newTester, tempTester)); does not work where I want it to?
You're right, there is undefined behaviour.
You're taking a reference to BreakIt.at(0); however this object is no longer guaranteed to exist after you've done a push_back, because if the vector grows, all of the contents are typically copied, and the originals deleted.
From http://www.cplusplus.com/reference/stl/vector/push_back/ (not the world's best reference):
Reallocations invalidate all previously obtained iterators, references and pointers.
For me, it was the issue with the MinGW version (MinGW g++ 6.3.0) which I updated to 7.2.0 from https://mingw-w64.org/doku.php/download.
Now it's working fine.

Why is this function segfaulting?

The function is this:
Set::Set(Multinumber* tempArray[], int tempSize)
{
numElements = tempSize;
capacity = tempSize*2;
setArray = new Multinumber*[capacity];
for (int i=0; i<numElements; i++)
{
addElement(tempArray[i]);
}
}
The variable setArray is declared in my header to be of type Multinumber**
It segfaults whenever I call it with this:
Multinumber* carr[2];
carr[0]=c4;
carr[1]=c5;
Set setb(carr,2);
c4 and c5 are already declared pointers to objects of the proper type.
Any help would be much appreciated.
EDIT: Code below is addElement function (apologies for the indentation)
const Set Set::operator+(const Set& rhs) const
{
Set result;
int i=0, j=0;
while ((i < numElements) && (j < rhs.numElements))
{
Multinumber* toadd=new Multinumber;
toadd=*(setArray[i]) + *(rhs.setArray[j]);
result.addElement(toadd);
i++;
j++;
}
while ((i < numElements))
{
result.addElement(setArray[i]);
i++;
}
while ((j < rhs.numElements))
{
result.addElement(rhs.setArray[j]);
j++;
}
return result;
}
EDIT:
Based on numerous cout statements, error seems to be in this function:
bool Set::isFull()
{
return (numElements == capacity);
}
EDIT: Changed array indices, but still segfaults
Arrays use zero-based indexes, so setting carr[2] to anything in a two-length array is undefined behavior. You should be grateful it was a segfault. :-)
Try:
Multinumber* carr[2];
carr[0]=c4;
carr[1]=c5;
Set setb(carr,2);
That should take care of the segfault.
carr[1]=c4;
carr[2]=c5;
Shouldn't that be
carr[0]=c4;
carr[1]=c5;
?
Piece of advice: If you load this up in a debugger, such as gdb, it would have identified the culprit line and you would've seen your error very quickly.