I am working on a school project for graphs and here I am doing a depth first search down the tree.
void wdigraph::depth_first(int v) const {
static int firstv = -1;
static bool *visited = NULL;
if (firstv == -1) {
firstv = v;
vector<bool> visited(size);
for (int i = 0; i < size; i++) {
visited[i] = false;
cout << visited[i] << endl;
}
}
cout << label[v];
visited[v] = true;
// visited[0] = true;
The first input value to the function is 0 (v = 0) and it crashes with that. size = 5. As you can see at the end of the code, I have tried to set visited to true manually with the same seg fault. When I remove all attempts to change visited, the program runs how it should normally without a seg fault.
Any ideas why this can't be modified? Also, there is more code but I have decided not to provide it unless necessary.
There are two different variables named visited in your code. Inside the if condition, visited is a vector, but outside this block, on the last line:
visited[v] = true;
visited refers to the bool *visited = NULL defined at the beginning of your code. The segfault occurs because you're trying to dereference a null pointer.
Related
Node* nodes[3];
for (Node* eachNode:nodes) {
eachNode = 0; //if i try to dereference it gives seg fault
} // eg. *eachNode = 0;
if (nodes[0] == 0) {
cout << "Null";
} else
cout << "Not null";
cout << '\n';
Node* nodes2[3];
for (int i = 0; i < 3; ++i) { //this way works fine
nodes2[i] = 0;
}
if (nodes2[0] == 0) {
cout << "Null";
} else
cout << "Not null";
Hi guys I am trying to make all my objects in an array equal to null. When using a for loop it works fine but when I use a foreach loop it breaks.
The output i get is
Not null
Null
I think i have to dereference the nodes in the foreach loop but it gives a seg fault.
Does anyone know whats wrong? thanks.
The loop you wrote loops over the values of the array:
for (Node* eachNode:nodes) {
eachNode = 0;
}
The above loop could as well have been written using auto:
for (auto eachNode:nodes) {
eachNode = 0;
}
The problem with the above loops is that eachNode is not the pointer stored in the array, but a copy of that pointer stored in a local variable of the loop.
If you wish to set the node to null, you need a reference to the memory location where you want to set it. You get that reference by referring to the array element using auto&:
for (auto& eachNode:nodes) {
eachNode = 0;
}
This last segment will likely do what you want.
I believe instead you should try:
for(Node *&eachNode : nodes) {
eachNode = nullptr;
}
This way you get a reference as opposed to the value, and you can appropriately set it to nullptr.
I'm not super experienced in C++ 11, but I did have a read here for more information about this new range construct.
Pointers are passed by value. So setting the eachNode = 0; will change the value, otherwise you are trying to dereference sonething that isn’t a pointer.
This question already has answers here:
How does C++ handle &&? (Short-circuit evaluation) [duplicate]
(7 answers)
Closed 7 years ago.
How does and operator evaluates its arguments. I have a code to check whether a graph is cyclic or not. In this code there is an and condition in an if statement. And I think, to the best of what I can make out is, that it terminates at the first encounter of a false expression without evaluating the second expression at all.
This is the code
bool Graph::isCyclicUtil(int v, bool *visited, bool *recStack){
if (visited[v] == false){
// Mark the current node as visited
visited[v] = true;
recStack[v] = true;
// Recur for all the vertices adjacent to this vertex
list<int>::iterator i;
for (i = adj[v].begin(); i != adj[v].end(); i++){
-------->**This and cond**if (!visited[*i] && isCyclicUtil(*i, visited, recStack))
return true;
else if (recStack[*i])
return true;
}
}
recStack[v] = false; // remove the vertex from the recursion stack
return false;
}
void Graph::printRecStack(bool *recStack){
cout << "\n \n";
for (int i = 0; i < V; i++){
if (recStack[i])
cout <<i<< "\n";
}
return;
}
bool Graph::isCyclic(){
// Mark all the vertices as not visited and not part of recursion stack
bool *visited = new bool[V];
bool *recStack = new bool[V];
for (int i = 0; i<V; i++){
visited[i] = false;
recStack[i] = false;
}
// Call the recursive helper function to detect cycle in different
// DFS trees.
if (isCyclicUtil(0,visited, recStack)){
printRecStack(recStack);
return true;
}
/*for (int i = 0; i < V; i++){
if (isCyclicUtil(i, visited, recStack))
printRecStack(recStack);
return true;
}*/
return false;
}
Please observe the and condition inside the if statement in isCyclicUtil function.
If you take a simple graph as a test case like this one:
0->1
1->2
2->0
2->3
3->3
And call isCyclicUtil for 0, the first 3 values in recStack comes out to be true. Which should have not been the case if the second expression was also evaluated in the if statement. Because call to node 2 will reach for its child 0. But since the loop started from 0, 0 is already visited, so recStack[0] should be initialized to false. But this does not happens, and all of them come out to be true. As if the and condition terminated as soon as it encountered visited[0] to be true, without even calling isCyclicUtil(0,visited,recStack) again.
That's correct. This is called short-circuiting and is a feature of many programming languages.
I am fairly new to the C++ language and I am trying to write a recursive method to traverse a tree. I have a traverse method but there is one line of code that causes a segmentation fault. I have tested this by commenting and uncommenting the line, compiling and executing. I have researched why segmentation errors are caused and do not see why any of what I am doing is causing a problem with the memory. Can someone give me advice about what I am doing wrong?
map<int, Node> theNodes;
void initialize()
{
// first we read the data
while (inStream.hasNext())
{
string nextLine = inStream.nextLine();
Node newNode = Node(nextLine);
this->theNodes[newNode.getSequence()] = newNode;
}
}
Code for getDownLinks() and getSequence
vector<int> downLinks;
int sequence;
vector<int> Node::getDownLinks() const
{
return this->downLinks; //
}
int Node::getSequence() const
{
return this->sequence;
}
Traversal Class Code
int totalPayoff;
Node headNode;
int Traversal::traverse()
{
Node headNode = theNodes[0];
std::vector<int> downLinks = headNode.getDownLinks();
for(int i = 0; i < downLinks.size(); i++)
{
int a = 0;
Node currentNode = theNodes[downLinks[i]];
traverseInner(a, currentNode);
}
return this->totalPayoff;
}
Here is the traverseInner function
int Traversal::traverseInner(int& level, Node& node)
{
std::vector<int> nodeDownLinks = node.getDownLinks();
if(nodeDownLinks.size() == 0)
{
totalPayoff = totalPayoff + node.getPayoff();
return 0;
}
for(int i = 0; i < nodeDownLinks.size(); i++)
{
int a = 0;
Node currentNode = theNodes[nodeDownLinks[i]]; <-- This causes segmentation error.
traverseInner(a, currentNode);
}
return totalPayoff;
}
Any variables that are not declared here are declared in the header file. The code compiles fine.
I'd also like to mention that I have written this code in many different ways and through my observations have come to the conclusion that any variable that is trying to be accessed in the braces of a nested statement cannot be accessed by the memory. Even the int a variable that is declared right above the problem statement and even hard coded data which is supposed to be there such as nodeDownLinks. If I try to print out through standard output the size of the vector inside one of the nested statements, I also get a segmentation error.
Probably the value inside "nodeDownLinks[i]" it is not initialized, having a memory random value, then you are trying to access this position in the
"theNodes" array and gives to you the segmentation fault.
Please, be sure the values inside "nodeDownLinks" are initialized.
99% it crashes because theNodes has less size, then nodeDownLinks[i] contains index. So nodeDownLinks[i] contains wrong index, u'd better check it and print what goes wrong this way:
int a = 0;
int link = nodeDownLinks[i];
if (theNodes.size() <= link)
std::err << "Wrong link " << link << " in Node" << std::endl;
else
traverseInner(a, theNodes[link]);
It shouldnt crash and you can find wrong index in nodeDownLink easily!
I am debugging a code dealing with vectors and iterators. I get an assertion error when I am clicking the "New" button on my GUI. The assertion error is that in the title, with the addition of /vector Line 251.
I have traced the problem to a part of the code attempting to remove an element from a vector. I will post the entire function and then the line that bugs:
int VsuCNTreeNodeManager::deleteTreeNode(RWCString & CNNameToDelete, RWTValSlist<VsuDeletedCN> & deletedCNList)
{
RWCString childName, parentName;
VsuCNTreeNode *pNode;
int i;
int size;
if (!nodeList.contains(CNNameToDelete))
return 1; // Means that CNNameToDelete doest not exist.
pNode = ordCNList[nodeList[CNNameToDelete]];
travForName.reset();
travForName.processElement(pNode);
const RWTValSlist<RWCString> & childNameList = travForName.getNameList();
size = childNameList.entries();
// If it is the Top node that is deleted then
// the VsuCNTreeNodeManager's top node pointer is reset.
if ( pNode == pTopCNTreeNode )
{
pTopCNTreeNode = NULL;
}
for ( i = 0; i < size; i++)
{
//******* How would it possible to have a name not contained in the nodeList
//******* since it has been extracted from the nodeList ?????????????
childName = childNameList.at(i);
if (nodeList.contains(childName))
{
//******* Process that get the Parent List of each deleted Tree Node
//******* The following code unref all the Tree Nodes that was referencing any deleted Tree Node
pNode = ordCNList[nodeList[childName]]; // Get the Tree Node to be deleted
// Fill the deletedCNList
deletedCNList.insert( VsuDeletedCN(childName, pNode->getCN()->hasType()) );
VsuDependencyRemoverVisitor visitor( *pNode );
for (unsigned int k = 0; k < pNode->getParentList().entries(); k++)
{
parentName = pNode->getParentList().at(k)->getCN()->getName();
if ( nodeList.contains(parentName) ) // Check if the parent is not deleted
{
//*** Remove the reference of the deleted tree node from that parent
RWBoolean status;
status = ordCNList[nodeList[parentName]]->removeElem(childName); // Removing the reference that pNode(parent) had on key(Child)
}
}
//******* Remove references on this object from observers.
pNode->resetObserverFlags();
pNode->updateAllObservers(&visitor);
//******* Process that delete all the Tree Nodes in the parentList
nodeList.remove(childName);
}
}
//*****************update Lists********************
size = ordCNList.entries();
int index = 0;
RWTValHashDictionary<RWCString, int> tmpNodeList(rwhash);
//nodeList.clear();
RWTPtrOrderedVector<VsuCNTreeNode> nodeToDelete(childNameList.entries());
for(i = 0; i < size; i++)
{
pNode = ordCNList[index];
childName = pNode->getCN()->getName();
if (!childNameList.contains(childName))
{
tmpNodeList.insertKeyAndValue(childName, index);
index++;
}
else
{
ordCNList.remove(pNode);
typeList[pNode->getCN()->hasType()].treeNodeList.remove(pNode);
// Decrement type counter and if it reach 0 then
// the entry is removed.
if( !typeList[pNode->getCN()->hasType()].treeNodeList.entries() )
typeList.remove(pNode->getCN()->hasType());
nodeToDelete.insert(pNode);
}
}
nodeList.clear();
nodeList = tmpNodeList;
ordCNList.resize(index);
if (!index)
pTopCNTreeNode = NULL;
for( unsigned int j=0; j < nodeToDelete.entries(); j++)
{
delete nodeToDelete[j];
}
return 0;
}
Now the line that bugs is:
RWBoolean status;
status = ordCNList[nodeList[parentName]]->removeElem(childName);
The definition of the removeElem function is:
RWBoolean VsuVE_Collection::removeElem(const RWCString & data)
{
VsuVE_Moveable *pMyObj = elementList.at(nameList[data]);
return removeElem1(pMyObj);
}
The definition of removeElem1 is:
RWBoolean VsuVE_Collection::removeElem1(VsuVE_Moveable *elem)
{
if (elementList.remove(elem) == FALSE) // THE ASSERTION ERROR HAPPENS RIGHT HERE
return FALSE;
//**** Reordering the nameList
nameList.clear();
int size = elementList.entries();
for (int i = 0; i < size; i++)
{
nameList.insertKeyAndValue(elementList.at(i)->name, i);
}
return TRUE;
}
My guess is that the removeElem function is attempting to remove a vector element that isn't there or that is out of the index range, but I am unable to figure out where exactly I can fix this. Any help is appreciated.
Thanks in advance
It's not obvious which particular framework you're using here (Rogue Wave?), but I think it may be possible to deduce the problem.
The key to decoding this assertion is understanding what incompatible iterators means. In general it means that you're trying to do an operation on a pair of items that don't refer to the same thing. For instance: (with standard library containers)
std::vector<int> v1, v2;
for (auto it=v1.begin(); it!=v2.end(); it++) { // <=== iterator incompatible
}
std::vector<int>::iterator it1=v1.begin();
v2.erase(v1); // <==== iterator incompatible
If you dig into the definition of the iterator types you have, then you should find that when the iterator is created it stores a reference back to the container it was created from. If you then perform an operation on two iterators (as in the first case above) then it can detect that they refer to different containers and hence aren't compatible. In the second case you have an operation on a container and an iterator, and so again it will assert that the iterator refers to that container.
In your case it appears that you're trying to remove an element from a container. The framework is asserting that the item isn't in the container (and in fact is probably in another). I suspect that you're deleting an item from the wrong container.
I'm trying to make function that has a loop that checks every member of an array made from boolean variables and exits when it finds the first "true" value.
That's what I have now:
bool solids[50];
int a,i;
//"equality" is a function that checks the equality between "a" and a defined value
solids[0] = equality(a,&value_1);
solids[1] = equality(a,&value_1);
solids[2] = equality(a,&value_1);
solids[3] = equality(a,&value_1);
for (i = 0; solids[i] != true; i++)
{
[...]
}
But I have no idea, what should I put into the loop?
My attempt was
for (i = 0; i <= 50; i++)
{
if (solids[i] == true)
{
return true;
break;
} else {
return false;
}
}
,that should return true after the first found true and return false if the array has no member with true value, but it doesn't seem to work in the code.
Is it wrong? If yes, what is the problem?
PS.: I may count the number of trues with a counter but that's not an optimal solve to the problem, since I just look for the FIRST true value and consequently, the program doesn't have to check all the 50 members. Needley to count, how many unnecesary steps should this solve would mean.
here's a short example usage of std::find() as advised by #chris:
bool find_element_in_array() {
bool solids[50];
int length;
/* ... do many operations, and keep length as the size of values inserted in solids */
bool* location = std::find(solids, length, true);
// if element is found return true
if (location != solids + length)
return true;
// else return false
return false;
}
Once you have solids correctly set (it looks like you're currently setting every value to the same thing), you can make a loop that exits on the first true like this:
for (i = 0; i < 50; i++)
{
if (solids[i] == true)
{
return true;
}
}
return false;
I'd also just move the declaration of i into the for loop body, since it's not used outside, but the above answers your question.
return immediately exits the function, so there is no need to break the loop after.
If it's sufficient to exit the function right after the search, you should write something like:
for (int i = 0; i < 50; i++) {
if (solids[i]) return true;
}
return false;
If you need to use the result of the search in the same function, use additional variable:
bool found = false;
for (int = 0; i < 50; i++) {
if (solids[i]) {
bool = true;
break;
}
}
if (found) { ...