Valgrind detects invalid read error in simple Iterator class - c++

Valgrind detects an invalid read error I don't know how to fix or to be more precise: I don't know what the problem is.
Invalid read of size 8
at 0x443212: std::vector<Tile*, std::allocator<Tile*> >::end() const
by 0x44296C: Collection<Tile*>::Iterator::operator++()
The Iterator class is very simple (and actually a somewhat bad piece of programming) but sufficient for my needs right now. I think there are three methods you should know to hopefully help find my problem:
Iterator(size_t x, size_t y, const TileCollection& tiles)
: mTiles(&tiles)
, mX(mTiles->begin())
, mY(mTiles->at(x).begin())
{
std::advance(mX, x);
std::advance(mY, y);
bool foundFirst = false;
while (!foundFirst)
{
while (mY != mX->end() && *mY == 0) ++mY;
if (mY != mX->end()) foundFirst = true;
else
{
++mX;
if (mX != mTiles->end()) mY = mX->begin();
}
}
}
Iterator Iterator::operator++()
{
bool foundNext = false;
++mY;
while (!foundNext)
{
while (mY != mX->end() && *mY == 0) ++mY;
if (mY != mX->end()) foundNext = true;
else
{
++mX;
if (mX != mTiles->end()) mY = mX->begin();
}
}
return *this;
}
void TileCollection::add(Tile* tile)
{
Point2D p(tile->getPosition());
std::vector<Tile*> tmp(1, (Tile*)0);
if ((size_t)p.x >= mTiles.size())
mTiles.resize(p.x + 1, tmp);
if ((size_t)p.y >= mTiles.at(p.x).size())
mTiles.at(p.x).resize(p.y + 1, (Tile*)0);
mTiles.at(p.x).at(p.y) = tile;
++mNumTiles;
}
The actual code that is causing the valgrind error is the line:
while (mY != mX->end() && *mY == 0) ++mY;
...of the Iterator::operator++ method.

It looks to me that, at the least, the following line in operator++
if (mX != mTiles->end()) mY = mX->begin();
is lacking a suitable else-clause.
Consider what happens when mX actually reaches mTiles->end(): You will enter a new iteration of the outer while loop; the first line in that loop (the line that causes the Valgrind error) will evaluate mX->end() and thus attempt to dereference mX -- but mX is mTiles->end(), and it's not correct to dereference the end iterator of a collection since it doesn't actually reference an element of the collection. It looks to me as if this may be the cause of your Valgrind error.
(Note that the constructor contains essentially the same code.)
More generally, I think you need to think about how you handle reaching the end of your two-dimensional array. How does the client of your Iterator check whether it has reached the end of the iteration? How do you expect your operator++ to handle the case when it reaches the end of the two-dimensional array? Should it protect itself against getting called too often?

You can try to split up the statement in order get find out where the error occurs:
while (mY != mX->end()) // maybe here
{
if (*mY != 0) // maybe here
{
break;
}
++mY; // maybe here
}
Compiling with GCC compiler option -fno-inline helps to get a nicer stack-trace, which can help you to trace the error. It will also make your program very slow, so don't forget to remove it later.

Related

C++ vector iterator not incremental

I've been having a headache with this problem. I've challenged myself to make a CLI space shooter, where you have you spaceship, lasers and meteors to shoot. The problem is this: whenever a laser or a meteor reaches the boundaries of our arena, I want to erase from the vector so that it wouldn't cluster it up. Here's how my working code looks now:
std::vector<Meteoras>::iterator itMet = meteorai.begin();
std::vector<Lazeris>::iterator itLaz = lazeriai.begin();
while (itMet != meteorai.end() || itLaz != lazeriai.end())
{
if (itLaz != lazeriai.end())
{
if (itLaz->getCoord()->x == j && itLaz->getCoord()->y == i)
{
itLaz->move();
++j;
if (itLaz->getCoord()->x >= ILGIS - 1) continue;
else std::cout << itLaz->getIcon();
}
++itLaz;
}
if (itMet != meteorai.end())
{
if (itMet->getCoord()->x - 1 == j && itMet->getCoord()->y == i)
{
itMet->move();
++j;
if (itMet->getCoord()->x <= 0) continue;
else std::cout << itMet->getIcon();
}
++itMet;
}
}
So there are two "continues" in there. Instead of them I tried placing iterator removals (as in itLaz = lazeriai.erase(itLaz) but that the program seemed to crash during runtime giving the error that I stated before. I tried doing other logical checks but that didn't seem to work either. I would appreciate if someone could explain a proper way of removing a useless object (in this case a meteor/laser) from a vector.
The comment about erase() invalidating an iterator is true. The part about needing to restart at the beginning is wrong. (You could do, but you certainly don't need to.)
erase() returns a still-valid iterator which points to the element after the erased item.
if( test for erasing )
{
itLaz = lazeriai.erase(itLaz);
}
else
{
++itlaz;
}
You might be able to refactor your code to use std::remove_if() instead.

Trouble removing elements from C++ vector

I'm trying to remove 'dead' bullets from my vector of bullets. Every frame, I'm calling the Bullet::update() function which looks like this:
void Bullet::update()
{
for(int i = 0; i != mAmmo.size(); i++)
{
if(mAmmo[i].sprite.getPosition().x > 700)
mAmmo[i].mAlive = false;
if(mAmmo[i].mAlive == false)
{
// I get a Debug Assertion Failed at runtime from this piece of code
mAmmo.erase(mAmmo.begin()+i);
}
if(mAmmo[i].mAlive == true)
{
mAmmo[i].sprite.move(mMovement);
}
}
}
Am I doing this completely incorrectly? This is the first time I've really used vectors more than just following through a tutorial. If I need to post any more code, just tell me. I've been working on this for the past few hours, so I'm a wee bit desperate to get this to work.
Thanks in advance!
You're easily walking into undefined behavior as soon as the ith element is the last element in your list. Use iterators, and pay special attention to the return value of erase(), as it automatically advances the iterator for you so your loop doesn't have to.
void Bullet::update()
{
for (auto it = mAmmo.begin(); it != mAmmo.end();)
{
if(it->sprite.getPosition().x > 700)
it->mAlive = false;
if (!it->mAlive)
{
// erase and get next iterator
it = mAmmo.erase(it);
}
else
{ // move and increment
it->sprite.move(mMovement);
++it;
}
}
}

C++ Break out of a vector loop

I have a method in a class LinkRepository, I am checking for duplicate entries in the vector array Datalinks, which is a member of the class. I loop through all the elements in the array to check in the new entry Datalink* datalink already exist in the array. If so then don't add, just exit the loop.
void LinkRepository::SaveLink(Datalink* datalink) {
bool Exist = false;
for(vector<Datalink*>::iterator dl = Datalinks.begin(); dl != Datalinks.end(); ++dl)
{
if((strstr((*dl)->ParentID, datalink->ParentID) != NULL) && (strstr((*dl)->ChildID,datalink->ChildID) != NULL))
{
Exist = true;
dl = Datalinks.end();
}
}
if(!Exist)
{
Datalinks.push_back(datalink);
}
};
My program seems to crash on the next loop of the statement dl = Datalinks.end();
I have no idea why it is crashing?
Replace
dl = Datalinks.end();
With:
break;
To exit the loop
Here is a simple example to illustrate why your solution can't work:
int i = 0;
for (; i != 10; ++i)
{
i = 10;
}
This loop will never end because i will be incremented to 11 before comparison i != 10
It is crashing because first you set the iterator to Datalinks.end() and then, upon leaving this iteration, the for loop itself increments the iterator, making an invalid operation.
for(vector<Datalink*>::iterator dl = Datalinks.begin(); dl != Datalinks.end() && !Exist; ++dl)
{
if((strstr((*dl)->ParentID, datalink->ParentID) != NULL) && (strstr((*dl)->ChildID,datalink->ChildID) != NULL))
{
Exist = true;
}
}
Like everyone had said you are iterating one over. So, it's going into unwanted memory locations resulting in a seg fault eventually. You have to realize that the ++dl is happening at the end of the loop.
Also, using a break statement here is ridiculous. You already have a bool, make use of it.

OpenCL Out of Resources - Crash at code line which is not reached at that moment

i'm doing some OpenCL programming and at one location in my code I get strange error.
a and a_end are pointers to local memory
if (a+POS<=a_end) {
max = ....
} else {
max = *(a_end-1);
}
In my case "else" isn't reached in the current loop. However, the application crashes with -5 CL_OUT_OF_RESOURCES if the line is part of the code.
If I comment the line the program works well. This is very strange.
Do you have any suggestions?
Regards,
Chris
Edit: Some more code
Values of a, a_end and POS1 before it crashes:
a: 3298304
a_end: 3311264
POS1: 34
border=b-b_end; //TODO: Check if all dummy elements are removed in this case
if(POS1<border && a+POS1<a_end) {
s_data[POS1+s_maxes[2]-border+1]=a[POS1];
s_ids[POS1+s_maxes[2]-border+1] = a_pos+POS1;
}
if(POS1+1==border) {
debug[0] = a+POS1;
debug[1] = a_end;
s_maxes[1]=*(b_end-1);
if(a+POS1<=a_end) {
s_maxes[0]=s_data[s_maxes[2]];
} else {
s_maxes[0]=*(a_end-1); //Here is the line where it crashes
}
}
if(POS2<border && a+POS2<a_end) {
s_data[POS2+s_maxes[2]-border+1]=a[POS2];
a_pos+POS2;
}
if(POS2+1==border) {
s_maxes[1]=*(b_end-1);
if(a+POS2<=a_end) {
s_maxes[0]=s_data[s_maxes[2]];
} else {
s_maxes[0]=*(a_end-1);
}
}
a+=border;a_pos+=border;
There is a good chance that the following scenario happens: before your if the value of a_end is corrupted, highly possibly it gets initialized to 0 (without further knowledge of the code this is my best shot, but it also might be a value which is smaller than a + POS) and then obviously the else branch gets executed which tries to de-reference the value found at address 0 - 1 which is a pretty big number and then the application crashes. Obviously if you remove the else branch this code is not executed.
Hint: Put some printouts for the value of a_end.

How can text in my main C++ file (in code that hasn't executed yet) show up in a string?

I'm new to C++ so there's a lot I don't really understand, I'm trying to narrow down how I'm getting exc_bad_access but my attempts to print out values seems to be aggravating (or causing) the problem!
#include <iostream>
#include "SI_Term.h"
#include "LoadPrefabs.h"
int main() {
SI_Term * velocity = new SI_Term(1, "m/s");
std::cout<<"MAIN: FIRST UNITS "<<std::endl;
velocity->unitSet()->displayUnits();
return 0;
}
The above code produces an error (EXC_BAD_ACCESS) before the std::cout<< line even occurs. I traced it with xcode and it fails within the function call to new SI_Term(1, "m/s").
Re-running with the cout line commented out it runs and finishes. I would attach more code but I have a lot and I don't know what is relevant to this line seeming to sneak backwards and overwrite a pointer. Can anyone help me with where to look or how to debug this?
NEW INFO:
I narrowed it down to this block. I should explain at this point, this block is attempting to decompose a set of physical units written in the format kg*m/s^2 and break it down into kg, m, divide by s * s. Once something is broken down it uses LoadUnits(const char*) to read from a file. I am assuming (correctly at this point) that no string of units will contain anywhere near my limit of 40 characters.
UnitSet * decomposeUnits(const char* setOfUnits){
std::cout<<"Decomposing Units";
int i = 0;
bool divide = false;
UnitSet * nextUnit = 0;
UnitSet * temp = 0;
UnitSet * resultingUnit = new UnitSet(0, 0, 0, 1);
while (setOfUnits[i] != '\0') {
int j = 0;
char decomposedUnit[40];
std::cout<<"Wiped unit."<<std::endl;
while ((setOfUnits[i] != '\0') && (setOfUnits[i] != '*') && (setOfUnits[i] != '/') && (setOfUnits[i] != '^')) {
std::cout<<"Adding: " << decomposedUnit[i]<<std::endl;
decomposedUnit[j] = setOfUnits[i];
++i;
++j;
}
decomposedUnit[j] = '\0';
nextUnit = LoadUnits(decomposedUnit);
//The new unit has been loaded. now check for powers, if there is one read it, and apply it to the new unit.
//if there is a power, read the power, read the sign of the power and flip divide = !divide
if (setOfUnits[i] == '^') {
//there is a power. Analize.
++i;++j;
double power = atof(&setOfUnits[i]);
temp = *nextUnit^power;
delete nextUnit;
nextUnit = temp;
temp = 0;
}
//skip i and j till the next / or * symbol.
while (setOfUnits[i] != '\0' && setOfUnits[i] != '*' && setOfUnits[i] != '/') {
++i; ++j;
}
temp = resultingUnit;
if (divide) {
resultingUnit = *temp / *nextUnit;
} else {
resultingUnit = *temp * *nextUnit;
}
delete temp;
delete nextUnit;
temp = 0;
nextUnit = 0;
// we just copied a word and setOfUnits[i] is the multiply or divide or power character for the next set.
if (setOfUnits[i] == '/') {
divide = true;
}
++i;
}
return resultingUnit;
}
I'm tempted to say that SI_Term is messing with the stack (or maybe trashing the heap). Here's a great way to do that:
char buffer[16];
strcpy(buffer, "I'm writing too much into a buffer");
Your function will probably finish, but then wreak havoc. Check all arrays you have on the stack and make sure you don't write out of bounds.
Then apply standard debugging practices: Remove code one by one until it doesn't crash anymore, then start reinstating it to find your culprit.
You are mentioning xcode, so I assume you're on a MAC. I'D then suggest looking at the valgrind tool from http://valgrind.org/ That's a memory checker giving you information when yo're doing something wrong with memory. If your program was build including debugging symbols it should give you an stacktrace helping you to find the error.
Here, I removed the unimportant stuff:
while (setOfUnits[i] != '\0') {
while ((setOfUnits[i] != '\0') && (setOfUnits[i] != '*') && (setOfUnits[i] != '/') && (setOfUnits[i] != '^')) {
...
++i;
}
...
nextUnit = LoadUnits(decomposedUnit);
...
if (...) {
double power = ...;
temp = *nextUnit^power;
delete nextUnit;
}
....
temp = resultingUnit;
delete temp;
delete nextUnit;
...
++i;
}
There are a number of problems with this:
In the inner-loop, you increment i until setOfUnits[i] == '\0', the end of the string. Then you increment i again, past the end of the string.
nextUnit is of type UnitSet, which presumably overloads ^. Though it's possible that it overloads it to mean "exponentiation", it probably doesn't (and if it does, it shouldn't): in C-based languages, including C++, ^ means XOR, not exponentiation.
You are deleting pointers returned from other functions - that is, you have functions that return dynamically-allocated memory, and expect the caller to delete that memory. While not incorrect, and in fact common practice in C, it is considered bad practice in C++. Just have LoadUnits() return a UnitSet (rather than a UnitSet*), and make sure to overload the copy constructor and operator= in the UnitSet class. If performance then becomes a concern, you could return a const UnitSet& instead, or use smart pointers.
In similar vein, you are allocating and deleting inside the same function. There is no need for this: just make resultingUnit stack-allocated:
UnitSet resultingUnit(0, 0, 0, 1);
I know that last bullet-point sounds very confusing, but once you finally come to understand it, you'll likely know more about C++ than 90% of coders who claim to "know" C++. This site and this book are good places to start learning.
Good luck!