C++ variable scope error inside for loop - c++

//Constructing set of all Places in Conflict with each other
int l_placeVec, l_placeVec1,p;
for(SP_ListListNode::const_iterator iter = m_postTransitionsSet.begin(),l_placeVec=0; iter != m_postTransitionsSet.end(); iter++,l_placeVec++) {
for(SP_ListListNode::const_iterator inneriter = m_postTransitionsSet.begin(),l_placeVec1=0; inneriter != m_postTransitionsSet.end(); inneriter++,l_placeVec1++) {
if((iter != inneriter) && ((**inneriter) == (**iter)) && (((int)((*iter)->size()))>1)) { //when the two lists are same
SP_ListNode* temper = new SP_ListNode;
temper->clear();
for(SP_ListNode::const_iterator iterplaces = m_placeNodes->begin(),p=0; iterplaces != m_placeNodes->end(); iterplaces++,p++) {
if((p == l_placeVec) || (p == l_placeVec1)) {
temper->push_back(*iterplaces);
}
}
m_conflictingPlaces.push_back(temper);
}
}
}
The above code is saying: "Unused variable p", though I am using it in the third for loop.
In case further information is required, please leave a comment.
But this is something weird I am facing.

You declared a completely different variable p in the inner loop. Here
for(SP_ListNode::const_iterator iterplaces = m_placeNodes->begin(),p=0; ...
The above is equivalent to declaring
SP_ListNode::const_iterator p = 0
which, of course, hides the outer p. The outer p remains unused, which is what the compiler is warning you about.
By a coincidence, this inner p is initializable with 0 and is comparable to int, even though its type is SP_ListNode::const_iterator, which is why there is no errors reported when you do this. But it is just a coincidence.
P.S. Just noticed that you did the same thing with all these outer int variables, which explains why the comparisons like p == l_placeVec do not fail.

"SP_ListNode::const_iterator iterplaces = m_placeNodes->begin(),p=0;" creates a new p of type SP_ListNode::const_iterator...so the outer p is not used.

Related

I don't know why this two-liner works

int countMatches(vector<vector<string>>& items, string ruleKey, string ruleValue) {
int idx = ruleKey == "type" ? 0 : ruleKey == "color" ? 1 : 2, res = 0;
return count_if(begin(items), end(items), [&](const auto &i) { return i[idx] == ruleValue; });
}
This is a problem off of leetcode. I attached the link below.
I will try and say what I think is going on, if anything is wrong - please correct me.
First, we are creating an int variable called idx. We assign it the current value of ruleKey (which is currently a string). If the string is "type", we assign idx the value of 0. If the string is "color", we assign idx the value of 1. If NEITHER of those two conditions pass, we assign idx the value of 2.
I don't know why res = 0 is even in the code, and I have no clue what is going on with the line of code that lies beneath. Especially with the [&](const auto &i) portion of the code.
I will try and say what I think is going on, if anything is wrong - please correct me.
Your understanding of the idx variable is correct.
I don't know why res = 0 is even in the code
It is simply declaring an unused variable res initialized to 0. Multiple variables of the same type can be declared in the same expression, eg:
int a = 0, b = 1;
In this case, yes res doesn't really belong and can safely be removed.
I have no clue what is going on with the line of code that lies beneath. Especially with the [&](const auto &i) portion of the code.
See the documentation for the std::count_if() algorithm and Lambda Expressions.
In a nutshell, std::count_if() loops through a range, calling a predicate for each element, and increments the result each time the predicate returns true. The code is using a lambda, ie an anonymous function type, for that predicate.
So, the code is iterating the items vector, counting how many of its inner vector elements have a value matching ruleValue at the index specified by idx. The code is basically equivalent to this:
int countMatches(vector<vector<string>>& items, string ruleKey, string ruleValue) {
int idx;
if (ruleKey == "type") idx = 0;
else if (ruleKey == "color") idx = 1;
else idx = 2;
int count = 0;
for(auto iter = items.begin(), end = items.end(); iter != end; ++iter) {
const auto &i = *iter;
if (i[idx] == ruleValue) ++count;
}
return count;
}

Why does the content of a pointer change?

I'm a C# programmer and now using C++ to do some work.
pair<Point,double>* p=NULL;
Sphere* sphere=NULL;
for (int i=0;i<spheres.size();i++)
{
vector<pair<Point,double>> solution=findIntersection(Point(ray.origin),Point(ray.direction.x,ray.direction.y,ray.direction.z),spheres[i]);
if(solution.size()==0)
continue;
if(p==NULL || solution[0].second<p->second)
{
p=&solution[0];
sphere=&spheres[i];
}
}
if(p==NULL)
return backgroundColor;
else
{
Color c=localIlluminate(p->first,*sphere);
return c;
}
I want p.first to have the smallest value, and sphere be the cooresponding sphere that is used to get p.
After debugging, I find the code doesn't work. In the first loop, p will be assigned the address of solution[0], assuming the value is {(0,0),0}. Then the loop continues and when i=1, assume solution[0] becomes {(1,2),3} and value of p also becomes {(1,2),3}.
I don't expect the value of p to change. How should I fix it?
You are storing the reference to a local variable outside the scope in which the local variable is declared.
Every iteration solution is not valid anymore, then the address to it shouldn't be considered valid. To obtain what you need you should assign the variable by value, so that you actually copy the contained value, eg:
pair<Point, double> p = std::make_pair(whatever, std::numeric_limits<double>::max());
for (...)
{
if (solution[0].second < p.second)
p = solution[0];
}
The fact that the address changes can be caused by multiple reasons, but you shouldn't bother understanding why, just avoid this kind of situation. Your misconception comes from the fact that C# has a garbage collection which prevents solution[0] from becoming invalid, which is not true for C++, when variable are declared on stack.
When you assign to p it points to the adresss of &solution[0] but on the next iteration of the loop that variable goes poof and a new one gets created and p points to either random stuff or something else.
It might be better to just store a copy in p, so make p a regular variable and copy over the solution[0] by assigning. You can have another bool variable to determine if a solution was found.
pair<Point,double> p;
Sphere sphere;
bool solutionFound = false;
for (int i=0;i<spheres.size();i++)
{
vector<pair<Point,double>> solution=findIntersection(Point(ray.origin),Point(ray.direction.x,ray.direction.y,ray.direction.z),spheres[i]);
if(solution.size()==0)
continue;
if(!solutionFound || solution[0].second < p.second)
{
p=solution[0];
sphere=spheres[i];
solutionFound = true;
}
}
if(!solutionFound)
return backgroundColor;
else
{
Color c=localIlluminate(p.first, sphere);
return c;
}

Unexplained Behavior with std::vector

In Stepping through some weird segmentation fault causing code, I found that after the assignment of one vector to another, the receiving vector arbitrarily corrupts. The following is a code snippet from a copy constructor of a class which has a data member vector<Piece> *pieces which is a dynamically allocated array containing vectors of type Piece.
ClassName::ClassName(const Class &other) // copy constructor of class
{
...
for(SIDE_t s = 0; s < sides; s++)
{
pieces[s].reserve(other.pieces[s].size());
pieces[s] = other.pieces[s]; //vector is completely valid here
for(Uint8 p = 0; p < pieces[s].size(); p++)
{
//it continues validity throughout loop
if(other.pieces[s][p].getCell() != NULL)
pieces[s][p].setCell(cells + (other.pieces[s][p].getCell() - other.cells));
if(pieces[s][p].getCell() == NULL)
out.push_back(&pieces[s][p]);
}
if(other.flags[s] != NULL)
flags[s] = getPiece(other.flags[s]->getValue(), other.flags[s]->getSide());
// vector is invalid in scope of getPiece, which receives completely valid arguments
else
flags[s] = NULL;
}
}
Piece * const ClassName::getPiece(const Uint8 num, const SIDE_t s) const
{
return (num>nPieces || s>sides || num == 0)? NULL:&pieces[s][num-1];
// Right here during the member access function of pieces,
// it is clear that the vector was corrupted some how
}
Essentially during debugging, I would step into pieces[s] member access function. In the loop body, it is evident that m_start has a valid address, however when it exits the loop body and calls the index operator on pieces[s] in getPiece, m_start is NULL. There are no operations performed on pieces[s] between the last iteration of the loop when m_start is valid, and in getPiece when during the same call of the index operator as in the loop body, m_start is NULL. Any insight on my misuse of std::vector or bugs in std::vector would be appreciated.
It looks to me that you have an access violation here:
return (num>nPieces || s>sides || num == 0)? NULL:&pieces[s][num-1];
First (as pointed out by Petr), it should read s>=sides.
Second, s here is not the same as s in the caller. So pieces[s] may not have been assigned yet and is an empty vector. To test it use
return (num>nPieces || s>=sides || num == 0)? NULL : &(pieces[s].at(num-1));
Btw, all this would have been avoided had you simply used
std::vector<std::vector<Piece>>
and copied the whole thing.

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.

Valgrind detects invalid read error in simple Iterator class

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.