Weird problem with lists structures and arrays - c++

I am implementing a path planning algorithm using graphs. In my implementation I have structures Node and Edge. One of the members of Node is a list of edges. I have a weird problem that came up in my code when I used a pointer to a node in an array, I've managed to isolate it below:
int main()
{
// Node node_array[5]; // If I use this array, the program works fine.
Node* node_array=(Node*)calloc(5, sizeof(Node) ); // This causes a problem
Node* pointer_to_node=&(node_array[0]);
pointer_to_node->id=0;
cout << "Did it work?" << "\n";//.
cout << pointer_to_node->id << "\n"; // This works fine
cout << (*pointer_to_node).id << "\n"; // This works fine
Node bla=*pointer_to_node; //This crashes the program. But if I remove the list of edges from Node, then it works fine.
cout << "Yes it worked!" << "\n"; // Something is breaking if I don't reach this.
}
The program crashes (exists without printing "Yes it worked!") when I try to dereference pointer_to_node. There are three things I've noticed.
-If I define a Node, form a pointer and then dereference it, there is no problem.
-If I create an array of nodes using Node node_array[5];, the program works fine.
-If I remove the list of edges member from Node, everything works fine.
I know there are probably many easier ways to implement something like this, but I'm curious to know what exactly am I breaking here to make the program crash. I'm new to c++ and Stack Overflow, so any feedback is appreciated.
Here is the rest of the code above main()
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <sys/types.h>
#include <time.h>
#include <sys/time.h>
#include <math.h>
#include <iostream>
#include <list>
using namespace std;
struct Node; // NOTE: we'll define this in detail later, but we need it now
struct Edge;
// this is a basic graph node
struct Node
{
int id;
list<Edge> edges; // these are edges from {nodes which this node can be accessed}
};
//basic edge data stucture
struct Edge
{
Node* startNode; // the edge starts at this node
Node* endNode; // the edge goes to this node
double edgeCost; // going along the edge cost this much
};

Your Node contains a list. This is a C++ class with its own non-trivial state.
The difference between Node node_array[5]; and calloc(5, sizeof(Node) ) is that the first one will actually call the constructors properly. The code bombs when trying to copy this badly initialized list somewhere else. If you want a dynamic allocation, use new Node[5] instead.

Related

Object created without keyword new out of scope within main function

I am attempting to implement a linked list in C++, when I create an object pointer without the keyword new, the code does not display anything. I have done some research and found that by using the new keyword this fixed this issue, but I am not entirely sure as to why this fixes it, I read that the pointer object may go out of scope and this "new" prevents that, but I do not understand how it goes out of scope.
Here is the code:
#include <iostream>
using namespace std;
struct Node{
int val;
};
int main(){
Node *head;
//Node *head = new Node; fixed the issue
head->val = 200;
cout << head->val;
return 0;
}

How do I read multiple variables into a node?

So my project is to get a file called "contacts.txt", read in the data and put the data into a node. Then, I put that node into a list. I purge duplicates and print out the resulting list. I'm trying to get the reading in the data and the printing part down first but I'm having problem printing out my list.
A line of contact looks like:
Angelina M. Pierre 306 420 1235
And each part of the line (first name, middle initial, last name, phone number) is supposed to have their own variable. I'm not really sure what I'm doing wrong and I would appreciate the help. My code is:
#include <iostream>
#include <bits/stdc++.h>
#include <stdlib.h>
#include <fstream>
using namespace std;
class Node
{
public:
string firstName;
string middleI;
string lastName;
string phoneNum;
Node *next;
};
// This function prints contents of linked list
// starting from the given node
void printList(Node* n)
{
while (n != NULL) {
cout << n->firstName->middleI->lastName->phoneNum << endl;
n = n->next;
}
}
//This function reads the data from a file called "contacts"
//And streams each line into a new node.
void readData(Node* &p)
{
Node *newNode = new Node; /* Initializing the node*/
ifstream fin("C:\\Users\\owner\\Documents\\contacts.txt");
p = newNode;
while(!EOF){
//fin >> firstName >> middleI >> lastName >> phoneNum;
//while(getline(fin,newNode->contacts)){
newNode->firstName;
newNode->middleI;
newNode->lastName;
newNode->phoneNum;
newNode->next = new Node;
newNode = newNode->next;
}
}
// Driver code
int main()
{
Node *head;
readData(head);
printList(head);
return 0;
}
There are a couple things that I think are majorly detracting from your program's performance. In your printList function, you have the line cout << n->firstName->middleI->lastName->phoneNum << endl;, and I assume here you intend to print all of the information for a user. What is happening here, however, is that the program takes the pointer n, attempts to find the firstName property of the object being pointed to, then takes this property and attempts to find the middleI property of that property, then the lastName property of that property, etc. These fields of course do not exist, so your program will likely crash. Rather, I think using something like cout << n->firstName << " " << n->middleI << " " << n->lastName << " " << n->phoneNum << endl; would work better.
Also, in your readData function, your while loop will continue to update the singular node p instead of creating new nodes, so (assuming that your input file is properly formatted and all that jazz) your head node, which is what is passed into this function when it is called by main(), will only be equal to the last contact in your file and your list will have a length of 1.
Incidentally, I see that you only have a Node class. If you are wanting to work with lists, you probably should create a second class (i.e. LinkedList) that takes one more level of abstraction. Your Node class, then, will handle setting/reporting its data and answering which node follows it, and your LinkedList class will handle keeping track of the list (by remembering where the head is), adding to/deleting from the list, and finding specific nodes in the list.
Some other considerations:
Variables held by a class should almost always be private instead of public. The reason for encapsulating the information in the first place, aside from organizing it, is to make sure that other parts of the program that have no business altering this portion of your code cannot touch it, and you lose this safeguard when you make everything public.
The functions that you are using to create/add nodes, print lists, etc., should all be methods (i.e. functions of a particular class). Say I have some class, Foo, which has a function that acts upon it named bar. To implement it, I could write something like:
class Foo {
private:
//Foo's variables
public:
void bar() {
//bar's implementation
}
}
You will be able to use the method bar() elsewhere because it is labeled public, and bar() will be responsible for handling any necessary manipulation of Foo's information.
It is considered bad practice to use using namespace std; because it can sometimes lead to ambiguous function calls and adding std:: is more explicit. See here for more information.
Using the keyword NULL is very C-style, whereas nullptr is considered more proper (and even safer) in C++. If you are curious, this seems to give a pretty in-depth explanation of this change.
Using while(!fin.eof()) is also considered wrong because !fin.eof() will only return true after you have finished reading the input file. Thus, you will attempt to read past the end of the file and this is plain dangerous. See here for more information.
A little lengthy, but I hope this clarifies things for you a bit! Feel free to comment if you have any questions.

Attempting to reference a deleted function (No reference to a funciton made)

I'm experiencing a problem at the moment where apparently I am Attempting to reference a deleted function. As far as I can see, I'm not actually referencing a function but a smart pointer to a struct.
This is a university project whereupon multiple header files and CPP files are being used to allow us to understand how to use multiple files in the same project and link them together along with understanding and making use of polymorphism. We are using multiple files as the brief states we must. The files and definitions were provided for us.
The following is supposed to conduct a "Breadth-first" search on a terrain map (array of numbers ranging from 0-3) from a starting location to the goal location. It is about path-finding.
This is what I have so far:
#include "SearchBreadthfirst.h" // Declaration of this class
#include <iostream>
#include <list>
using namespace std;
bool CSearchBreadthFirst::FindPath(TerrainMap& terrain, unique_ptr<SNode> start, unique_ptr<SNode> goal, NodeList& path)
{
// Initialise Lists
NodeList closedList; // Closed list of nodes
NodeList openList; // Open list of nodes
unique_ptr<SNode>currentNode(new SNode); // Allows the current node to be stored
unique_ptr<SNode>nextNode(new SNode); // Allows the next nodes to be stored in the open list
// Boolean Variables
bool goalFound = false; // Returns true when the goal is found
// Start Search
openList.push_front(move(start)); // Push the start node onto the open list
// If there is data in the open list and the goal hasn't ben found
while (!openList.empty() || goalFound == false)
{
cout << endl << "Open list front:" << openList.front() << endl;
currentNode->x = openList.front()->x;
currentNode->y = openList.front()->y;
currentNode->score = openList.front()->score;
currentNode->parent = openList.front()->parent;
}
}
It's highlighting this line: currentNode->x = openList.front()->x; as the problem.
The NodeList type is defined in SearchBreadthfirst.h as the following:
using NodeList = deque<unique_ptr<SNode>>;
SNode is also defined in SearchBreadthfirst.h as such:
struct SNode
{
int x; // x coordinate
int y; // y coordinate
int score; // used in more complex algorithms
SNode* parent = 0; // note use of raw pointer here
};
The program breaks upon build. I've been trying to wrap my head around this for days now, so any help is greatly appreciated. If I've missed anything out, let me know and I'll add it in!
James
The error message Attempting to reference a deleted function is due to the fact that std::unique_ptr explicitly deletes its copy constructor because, obviously, there's only supposed to be one copy of the pointer it contains.
When you call
openList.push_front(start);
You're creating a copy of start which is of type unique_ptr<SNode> and it has a deleted copy constructor. In order to use a std::unique_ptr with a container, you need to move the object into the container. You need to do something like this:
openList.push_front(move(start));
That will move start into the deque and move what was in there into start.

Copy constructor for a vector of pointers

I'm trying to create a node class that contains a vector of pointers. Here's my code:
node.h:
#ifndef NODE_H
#define NODE_H
class node
{
public:
vector<node*> next;
void add_arc(node & a)
string some_string;
#endif
node.cpp:
void node::add_arc(node & a)
{
node *b = &a;
next.push_back(b); //only copyies nodes
}
main.cpp:
int main()
{
vector<node> nodes;
node a;
node b;
node c;
a.somestring = "a";
b.somestring = "b";
c.somestring = "c";
a.add_arc(b); //a should point to b
a.add_arc(c); //a should point to c
nodes.push_back(a);
nodes.push_back(b);
nodes.push_back(c);
cout << nodes[0].next.size() << endl; // prints "2", works fine
cout << nodes[0].next[0]->some_string << endl; //empty
}
I thought it would be as easy as just overloading push_back:
void push_back(vertex * pointer)
{
next.push_back(pointer);
}
But I think I really need a copy constructor, or some other method to make this work. How would I go about doing this for a vector of pointers?
Edit: I guess I didn't explain it well. Look at the answers in this question:
Segmentation fault when accessing a pointer's member function in a vector
Making 'a' a reference did not work for me
It works...
Your code generates as expected the correct output (see online demo):
2
b
...However this design is not future proof
However this result is related somehow to luck, because in your code snippet:
the nodes in the nodes vector are copies of the original object including all their pointers
the local objects a, b, c to which these pointers point still exist
However in more complex code, you'd quickly end up with dangling pointers.
Imagine:
Bad example 1: you create a graph, keeping all the nodes directly in a vector of nodes. You then add the first arcs between the nodes. As soon as you'll add a new node to the vector, reallocation might occur and you'd risk to see all your next pointers invalidated.
Bad example 2: you initialise a graph like you did, but in a function called by main. In this case, as soon as you return from this function, all the local nodes get destroyed and the vector's node will point to objects that do no longer exist. UB guaranteed !
How to improve ?
Your design fails to recognize that the nodes all belong to the same graph.
There is a quick and dirty way out: always create the node from the free store, and store them in a vector<node*>.
vector<node*> nodes;
node *a = new node("a"); // Imagine a node constructor
node *b = new node("b");
a->add_arc(b); //change signature, to accept a pointer
nodes.push_back(a);
nodes.push_back(b);
There's a better approach: improve further the previous approach, but use shared_ptr<node*> to make sure that nodes that are no longer referenced (neither by a vector of nodes, nor by an arc) are destroyed automatically.
There's an even better approach: encapsulate the nodes in a class representing a graph. In this case, you could consider using a vector<nodes> and replace the pointers in next, by indexes of the target nodes in the vector. No pointer, but perfect copy of graphs will be much easier. And no more memory management hassle.
class node // just to give the general idea
{
public:
vector<int> next; // not usable without the graph
void add_arc(int a)
string id;
};
class graph {
vector<node> nodes;
public:
void add_node (node a);
void add_arc (string from, string to);
node& operator[] (size_t i);
...
};

Seg faults at particular line, can't figure out why

The program seg faults once it reaches this line of code (the code is in Graph.cpp in the function set_array.)
adjList[adjList.size()].push_back(Edge(vertex, 0));
Basically, I want this line to be called every time i need to make the vector longer to fit more linked lists, as the structure is an vector of linked lists. Here is the .h file that declares the vector of linked lists and its contents. Every node will contain a vertex and a weight. (The node class is known as class Edge.)
#ifndef GRAPH_H_INCLUDED
#define GRAPH_H_INCLUDED
//class MinPriority;
#include <iostream>
#include <string>
#include <vector>
#include <list>
using namespace std;
class Graph
{
public:
Graph();
~Graph();
void set_Edge(string targetVertex, string vertex, int weight);
void set_array(string vertex);
void print_Test();
friend class MinPriority;
private:
class Edge
{
public:
Edge(string vertex, int weight)
{m_vertex = vertex; m_weight = weight;}
~Edge(){}
string m_vertex;
int m_weight;
};
vector< list<Edge> > adjList; //declaration of the array of linked lists
};
#endif // GRAPH_H_INCLUDED
here is what I want adjList[adjList.size()].push_back(Edge(vertex, 0)); to do; basically every time I want to insert a new vertex into the graph, I will call this. It seg faults as soon as I try to put the first item in the tree. Ill call to insert 'A' with a weight of '0' and it will immediately seg fault. By the way, I am trying to make an adjacency list where i use adjList[adjList.size()].push_back(Edge(vertex, 0)); to add a new (unused) vertex into the graph. Lets pretend this is passed into the function...
A B C D
After doing this, the vector's length should increase by 4. But of course it instead seg faults at that line (it tells me in GDB). I'm very new to using wierd data structures like this so any help would be very appreciated.
Try
adjList[adjList.size()-1]
The arrays are indexed 0..(size-1).
For instance, the indices of a 4 element array are 0, 1, 2 and 3.
If there is a possibility that the array is empty, you can add logic to prevent any access at all --
if (adjList[adjList.size() > 0) ...
Try to cast your array index :
adjList[int(adjList.size())]
Or try with 0 ?
EDIT : It seems you have to manually enter the lists before pushing Edge elements in it.
// Creation of independant lists
list<Edge> Eg, Ec;
Edge h("AB", 0);
Edge f("CD", 0);
adjList.push_back(Eg);
adjList[adjList.size()-1].push_back(h);
adjList.push_back(Ec);
adjList[adjList.size()-1].push_back(f);
// Return 2
cout << adjList.size();
I haven't found another way yet. But i'm no c++ expert.