Unexplained Behavior with std::vector - c++

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.

Related

vector pop_back causing heap-buffer-overflow error

I'm trying to make a function to validate the parenthesis problem, this function runs well on my machine, but it causing "heap-buffer-overflow" error on leetcode machine when I call vector.pop_back(). Here's the code:
int isValid(string s){
vector<char> st;
for(int i = 0; i < s.length(); i++){
if(s[i] == '(') st.push_back(s[i]);
else{
if(st.back() == '(') st.pop_back(); //this line triggered the error
else return 0;
}
}
return (st.size() == 0);
}
I already solved this by changing the vector into string, but I'm still wondering how can this happened, any explanation anyone?
Calling std::vector::back() on an empty vector is undefined behavior.
Calling back on an empty container causes undefined behavior.
(The same holds for std::vector::pop(), but at that point your program is already in an invalid state if the container was empty).
Therefore, the expression st.back() == '(' on your code might lead to an invalid program state because the container st is not sure being not empty.
Your code path needs to check the emptiness of the container before calling std::vector::back(); something like:
if (!st.empty() && st.back() == '(')
st.pop_back();
else
return 0;
Bonus Note: the code above exploits logical operators short circuit evaluation. It means that the second operand (i.e., the expression st.back()) will not be invoked if the container is empty.
maybe because you didn't assign any element in the vector before checking on the if condition. Try putting :
if(st.size()!=0)
{
if(st.back() == '(') st.pop_back();
else return 0;
}
on that piece of code

Problems implementing recursive best-first search in C++ based on Korf 1992

I am having two main issues implementing the algorithm described in this article in C++: properly terminating the algorithm and freeing up dynamically allocated memory without running into a seg fault.
Here is the pseudocode provided in the article:
RBFS (node: N, value: V, bound: B)
IF f(N)>B, return f(N)
IF N is a goal, EXIT algorithm
IF N has no children, RETURN infinity
FOR each child Ni of N,
IF f(N) < V AND f(Ni) < V THEN F[i] := V
ELSE F[i] := f(Ni)
sort Ni and F[i] in increasing order of F[i]
IF only one child, F[2] := infinity
WHILE (F[1] <= B)
F[1] := RBFS(N1, F[1], MIN(B, F[2]))
insert N1 and F[1] in sorted order
return F[1]
Here, f(Ni) refers to the "computed" function value, whereas F[i] refers to the currently stored value of f(Ni).
Here is my C++ implementation, in which I had to use a global variable to keep track of whether the goal had been reached or not (note, I am trying to maximize my f(n) value as opposed to minimizing, so I reversed inequalities, orders, min/max values, etc.):
bool goal_found = false;
bool state_cmp(FlowState *lhs, FlowState *rhs)
{
return (lhs->value > rhs->value);
}
int _rbfs(FlowState *state, int value, int bound)
{
if (state->value < bound) // Returning if the state value is less than bound
{
int value = state->value;
delete state;
return value;
}
if (state->is_goal()) // Check if the goal has been reached
{
cout << "Solved the puzzle!" << endl;
goal_found = true; // Modify the global variable to exit the recursion
return state->value;
}
vector<FlowState*> children = state->children();
if (children.empty())
{
//delete state; // Deleting this state seems to result in a corrupted state elsewhere
return INT_MIN;
}
int n = 0; // Count the number of children
for (const auto& child: children)
{
if (state->value < value && child->value < value)
child->value = value;
else
child->update_value(); // Equivalent of setting stored value to static value (F[i] := f(Ni))
++n;
}
sort(children.begin(), children.end(), state_cmp);
while (children.front()->value >= bound && !goal_found)
{// Loop depends on the global goal_found variable since this is where the recursive calls happen
if (children.size() < 2)
children.front()->set_value(_rbfs(children.front(), children.front()->value, bound));
else
children.front()->set_value(_rbfs(children.front(), children.front()->value, max(children[1]->value, bound)));
}
// Free children except the front
int i;
for (i = 1; i < n; ++i)
delete children[i];
state->child = children.front(); // Records the path
return state->child->value;
}
void rbfs(FlowState* initial_state)
{
// This is the actual function I invoke to call the algorithm
_rbfs(initial_state, initial_state->get_value(), INT_MIN);
print_path(initial_state);
}
My main questions are:
Is there a way to terminate this function than having to use a global variable (bool goal_reached) without a complete re-implementation? Recursive algorithms usually have some kind of base-case to terminate the function, but I am not seeing an obvious way of doing that.
I can't seem to delete the dead-end state (when the state has no children) without running into a segmentation fault, but not deleting it results in unfreed memory (each state object was dynamically allocated). How can I modify this code to ensure that I've freed all of the states that pass through it?
I ran the program with gdb to see what was going on, and it appears that after deleting the dead-end state, the next state that is recursively called is not actually NULL, but appears to be corrupted. It has an address, but the data it contains is all junk. Not deleting that node lets the program terminate just fine, but then many states aren't getting freed. In addition, I had originally used the classical, iterative best-first search (but it takes up far too much memory for my case, and is much slower), and in that case, all dynamically allocated states were properly freed so the issue is in this code somewhere (and yes, I am freeing each of the states on the path in main() after calling rbfs).
In your code, you have
children.front()->set_value(_rbfs(children.front(), ...
where state inside of _rbfs is thus children.front().
And in _rbfs, you sometimes delete state. So children.front() can be deleted and then called with ->set_value. There's your problem.
Is there any reason why you calling delete at all?

Vector iterators incompatible... but why?

I receive the message "Vector iterators incompatible". I tried to wrap my head around it, but nothing. I did it before. Same code, just not used in a class that receives "cWORLD* World". What am I doing wrong?
Thank you!
else if (Click[2] == true)
{
//go through objects and check collision
for (vector<cOBJECT*>::iterator it = World->ReturnWorldObjects().begin(); it != World->ReturnWorldObjects().end();)
{
//Check for collision and delete object
if (PointInRect(MouseX + offX, MouseY + offY, (*it)->getrect()) == true)
{
// delete object, delete slot, pick up next slot
delete *it;
it = World->ReturnWorldObjects().erase(it);
}
else
{ // no action, move to next
++it;
}
}//for
}//else if (Click[2] == true)
Looks like ReturnWorldObjects returns copy of vector, not reference. In this case, you are trying to compare iterators of different objects, that is not checked by standard, but can be checked by checked iterators (in this case, I think it's MSVC checked iterators).
Like #ForEveR already mentioned, you possibly return a copy of a vector in the function ReturnWorldObjects(). Without seeing the declaration of this method I can only assume it's something like vector<cOBJECT*> ReturnWorldObject();
You can come around this with 2 Solutions, I think:
1. Return a reference to the vector in your World Class
const vector<cOBJECT*>& ReturnWorldObjects()
{
return m_vecWorldObjects; // Your vector here
}
2. Get one copy of that function and use that in your code
...
vector<cOBJECT*> worldObjects = World->ReturnWorldObjects();
for (vector<cOBJECT*>::iterator it = worldObjects.begin(); it != worldObjects.end(); it++)
{
...
}
...

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

C++ variable scope error inside for loop

//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.