I am trying to write a program that will solve a maze using a class and a tree. I am trying to use a class to represent the maze (the design will be entered using cin), and the class contains a struct as a private member.
This struct contains two ints (for the x and y coordinate of the position) and an array with 3 spaces that will hold three pointers to other structs.
In the constructor function for my class, I am trying to set all the pointers in the array to NULL to start off. The program compiles fine, but when I get to the constructor the program gives me a segmentation fault. Here is some relevant code:
const int POSSIBLE_BRANCHES = 3; //at any point the path can split in 3 ways
struct PathNode
{
int x_coord;
int y_coord;
PathList branches[POSSIBLE_BRANCHES];
};
typedef PathNode *PathList;
class Maze
{
private:
PathList initial_pos;
public:
Maze();
};
And the constructor:
Maze::Maze()
{
cout << "entered constructor" << endl;
for (int i = 0; i < POSSIBLE_BRANCHES; i++)
{
initial_pos->branches[i] = NULL;
}
}
I get the "entered constructor" phrase printed out, but the program stops immediately afterwards. I am assuming it is some silly problem with my pointer syntax, but I have been unable to locate the problem.
As I understand it: the -> operator dereferences the pointer to the PathNode struct, so now we have access to the members like x_coord, y_coord, and branches. The [] operator gets to each index of the branches array. And because it is an array of pointers to PathNodes, setting them as NULL should be fine. Where is the flaw in my reasoning?
Edit:
Solved. See the answer marked as best.
You haven't yet allocated initial_pos before you use it. That is causing the segfault.
Something along the lines of:
Maze::Maze()
: initial_pos(new PathNode)
{
cout << "entered constructor" << endl;
for (int i = 0; i < POSSIBLE_BRANCHES; i++)
{
initial_pos->branches[i] = NULL;
}
}
Should fix your problem.
Your constructor is the first thing that gets called for the new class, so you never allocate or initialize initial_pos in anyway, but you then dereference it - leading to undefined behavior (most likely causing a segfault)
Related
For some reason I'm getting a segmentation fault; I'm using a vector of pointers, which point to a class object. Basically I need a node that has a vector of pointers to other nodes, in other to make a multigraph. Here's the relevant part of my code:
node.h:
#ifndef NODE_H
#define NODE_H
class node
{
public:
string content()
vector<node*> next; //causing the error
void add_arc(node a);
string rna_frag;
#endif
node.cpp:
void node::add_arc(node a)
{
node *b = &a; //b->content() works fine here
next.push_back(b);
}
string node::content()
{
return rna_frag;
}
main.cpp:
int main()
{
vector<node> nodes;
node a;
node b;
node c;
a.add_arc(b);
a.add_arc(c);
a.rna_string = "G";
nodes.push_back(a);
nodes.push_back(b);
nodes.push_back(c);
cout << nodes[0].content() << endl; //prints "G", works fine
cout << nodes[0].next.size() << endl; // prints "2", works fine
cout << nodes[0].next[0]->content() << endl; //segmentation fault
//cout << nodes[0].next->content() << endl; //also segmentation fault
//cout << nodes[0].next[0]->rna_frag << endl; //also segmentation fault
}
in this case, nodes[0]'s string is "G" and is pointing to 2 other nodes, so the first 2 couts are working perfectly. But when I access the vector's contents it just crashes and gives a segmentation fault error. Anyone know why?
In add_arc you are storing the address of the parameter a, which is then destroyed when the function exits - so you have undefined behaviour.
You're also copying nodes when you call nodes.push_back(), which is going to cause you a lot of grief.
You are going to need to either stop copying or write a proper copy constructor (and then follow the rule of 3, or 5).
With
void node::add_arc(node a)
{
vertex *b = &a; //b->content() works fine here
next.push_back(b);
}
you add in next the pointer to an object that is destroyed exiting from the method (a).
Using it...
cout << nodes[0].next[0]->content() << endl;
crash!
Suggestion: transform next in a vector of nodes (not pointer of nodes)
If you do vector.push_back(a) the node in the vector is a copy (stored at a different memory adress). Moreoever your add_arc takes its parameter by value and the node you push into the vector is local to that function. Once this you leave the scope of this function dereferencing that pointer is undefined behaviour.
You should consider passing the argument by reference, or in that case even simpler a pointer to the node you want to add. However, also then you have to be aware that in your main this...
vector<node> nodes;
node a;
node b;
a.add_arc(b);
nodes.push_back(a);
nodes.push_back(b);
would not be what you want, because now a has b added as arc, while the second entry of the nodes vector is a copy of b. Maybe in that case it would be easier to use a vector<node*> nodes because you can copy pointers and they will still point to the same object.
The book I'm using wants me to implement LIFO stacks using constructors in C++. The first implementation is fairly easy because it wants me to pass the object in a function by reference (so the code below has an additional & in pushexternal function).
However, I don't know how to properly implement the second version of it. It wants me to make it by passing the object by value. Therefore, it creates a copy of the object and after using a push function on a stack, the pushed element is gone. I don't know how to properly do it when passing it by value. I was thinking about using a copy constructor somehow, but I've tried it and it doesn't seem to work...
This is the code that is written in the book. I'm not supposed to modify it, I can only write my own class / additional functions:
void pushexternal(Stack s, int a) {
s.push(a);
}
int main() {
Stack s;
s.push(0);
s.push(1);
s.push(2);
pushexternal(s, 3);
pushexternal(s, 4);
return 0;
}
And this is a part of my implementation:
#include <iostream>
using namespace std;
class Stack {
public:
int ind;
int * arr;
Stack()
{
arr = new int[25];
ind = -1;
}
~Stack()
{
delete [] arr;
}
void push(int val)
{
arr[++ind] = val;
cout << "Added " << arr[ind] << " to " << ind << endl;
}
};
I'm aware that passing by value is not recommended here, but I'm really wondering how can I make it work properly when pass by value is mandatory. The only thing that comes to my mind is writing some kind of a copy constructor...?
Of course, my code doesn't work here as it makes a copy that is supposed to push a variable, but when passing by value, it's gone when it exits the function...
The results of this program should look like this:
Added 0 to 0
Added 1 to 1
Added 2 to 2
Added 3 to 3
Added 4 to 4
If you were to allocate an extra member in your arr member, you could then use arr[0] instead of ind as your index. That way, even if your stack object is copied by value, the arr pointer will still point to the same memory.
Similar, possibly more complex solutions exist, involving having your object contain a pointer to a structure with both ind and arr in it.
I am fairly new to using pointers in C++ but I will try and explain what I want to do.
I have a class object Rx (receiver), and in my program I will be using multiple receivers at the same time. Each receiver has a vector of data (observations), for simplicity I am just using a vector of doubles. I also have an array of bools that determine which observations to use and I would like each receiver (as a member variable) have a pointer to this array. For example the first element in the array of bools will say "true or false use the first observation you have receiver".
Also, further in my code I would also like to point to an array of objects, would I follow the same procedure?
int main()
{
// The elements in this array are set in the code before
bool use_observations[100];
// I have chosen 3 for an example but in my actual code I have a vector
// of receivers since the quantity varies
Rx receiver_1, receiver_2, receiver_3;
// I would like to set the pointer in each receiver to point
// to the array use_observations
receiver_1.SetPointer(use_observations);
receiver_2.SetPointer(use_observations);
receiver_3.SetPointer(use_observations);
} // end of main()
My receiver class declarations and definitions:
class Rx{
public:
Rx(); // Constructor
Rx(const Rx& in_Rx); // Copy constructor
~Rx(); // Destructor
void SetPointer(bool* in_Array); // Function to set pointer to use_observation
private:
std::vector<double> data;
bool* pointer_to_array[10];
}; // end of class Rx
void Rx::SetPointer(bool* in_Array)`{*pointer_to_array`= in_Array);
This is where I get the problems, either it doesnt assign correctly (get lots of nulls or not assigned) or I get an error on pointer_to_array saying expression must be a modifiable value
I haven't bothered showing the constructor, copy constructor and Destructor. I know normally in the destructor you should delete the pointer however Rx does not own the data in the array so I do not want to delete it.
Thanks for your help
EDIT** I have shown some code that I am using and what I get for results and I have modified SetPointer() to display some results
int main
{
bool use_observations [6] = {true, true, true, true, true, true};
Rx receiver_1;
receiver_1.SetPointer(use_observations);
}
void Rx::SetPointer(bool* in_Array)
{
*pointer_to_array = in_Array;
for(int i = 0; i < 6; i++)
{
if(*pointer_to_array[i] == true)
std::cout << "Good" << std::endl;
} // end of for loop
} // end of SetPointer()
When I debug and step over (*pointer_to_array = in_Array) I get the result
{true, and 0xCCCCCCCC for the rest of the elements} and then on the second iteration of the for loop it crashes saying "Access violation reading location 0xCCCCCCCC
SECOND EDIT **
Thank you everyone for your help. #PaulMcKenzie pointed out in his implementation (in the comments) in Rx that I should have bool* pointer_to_array not bool* pointer_to_array[6] and that solved the issue. As well I should be pointing to the start of the array buffer, not a pointer to the array.
The issue is that you want a pointer to the start of the array buffer, not a pointer to the array.
class Rx{
public:
void SetPointer(bool* in_Array);
bool* pointer_to_array;
};
void Rx::SetPointer(bool* in_Array) {pointer_to_array = in_Array);
Note the removal of the *.
everyone!
I just finished writing a 2-D maze (Class is an ADT titled "Maze"--how original) that uses dynamic memory allocation. I'm passing the Maze to a method of another class I've entitled "MazeSolver," which uses recursion and backtracking to solve the maze. Good news is my code compiles wonderfully when I pass the object by reference. News that I don't know if is good or bad is that I get an assertion error if I try to pass the Maze to MazeSolver by value.
Given that the error occurs only when I pass by value, I can only assume it has something to do with my copy constructor. Before going any further, here's some info on the code:
Maze is composed of squares. Each square is represented by a struct called SquareData.
struct SquareData
{
//data fields for the struct (NO POINTERS)
}
I've decided to represent the entire maze with a vector of SquareData pointers (this vector is in private section of the class "Maze").
vector<SquareData*> squares;
Implementation of my destructor looks like this (that last call referencing a Player class is just eliminating a dangling pointer I have declared as a static variable for that class, which I have pointing at the maze. I don't think it's important considering the question, but I am new to C++ after all and one of you may think it might be, so I've included it for "hmmms"):
// clears maze of its contents
void Maze::clear() {
int totalSquares = squares.size();
for (int loopVar = 0; loopVar < totalSquares; loopVar++)
{
delete squares[loopVar]; // deallocate memory by deleting the square structure
squares[loopVar] = nullptr; // eliminate dangling pointer
} // vector takes care of itself
} // end clear
Maze::~Maze(){
//clear the maze of contents (vector is full of pointers whose memory is on the heap)
clear();
//vector safe to deallocate itself now
Player::setMaze(nullptr); // remove the pointer from player
}
I've declared the copy constructor in header as follows:
/** Copy Constructor */
Maze(const Maze& myMaze);
with attempted implementation:
/** copy constructor */
Maze::Maze(const Maze& myMaze){
/** Initialize Constants */
mazeLength = myMaze.mazeLength;
mazeWidth = myMaze.mazeWidth;
exitRow = myMaze.exitRow;
exitCol = myMaze.exitCol;
entRow = myMaze.entRow;
entCol = myMaze.entCol;
/** copy the vector of pointers*/
for (int loopVar = 0; loopVar < myMaze.squares.size(); loopVar++)
{
squares.push_back(myMaze.squares[loopVar]);
}
} // end copy constructor
Here's how I attempted to understand what the problem was doing:
I wrote this vector display function in for my Maze class.
void Maze::vectorDisplay() const {
for (int loopVar = 0; loopVar < squares.size(); loopVar++)
{
cout << "Vector Index: " << loopVar << endl;
cout << "Pointer: " << squares[loopVar] << endl;
cout << "Row: " << squares[loopVar]->Row << endl;
cout << "Col: " << squares[loopVar]->Col << endl;
cout << "State: " << squares[loopVar]->State << endl;
}
} //end vectorDisplay
And found that the vector displays correctly when doing the following in the driver:
Maze myMazeObject(// parameters);
myMazeObject.vectorDisplay();
and will produce output with no complaints.
But now if I try to use code like this when passing by value:
Maze myMazeObject(// parameters);
MazeSolver myMazeSolver;
myMazeSolver.someMazeSolverMethod(myMazeObject);
where someMazeSolverMethod has the line myMazeObject.vectorDisplay();I get an assertion error just as the final element in the vector is being printed.
I want to say this is my fault and my copy constructor is a p.o.s. If any insight, please let me know how to fix it and what I can do in the future!
Thanks for taking the time to read and even more so to answer should you choose to!
-J
This is your problem.
squares.push_back(myMaze.squares[loopVar]);
Basically each Maze has a vector full of the same pointers. When one copy of the maze goes out of scope it will delete all the pointers. Thus the other Maze now has a set of invalid pointers.
Couple of solutions.
Don't use pointers.
Unless you SquareData is polymorphic there seems no reason to keep pointers.
std::vector<SquareData> squares;
If you want each copy of the maze to refer to the same squares.
Then use a shared pointer. This will keep a count of the number of references to each SquareData and thus only delete them when they truly go out of scope.
std::vector<std::shared_ptr<SquareData>> squares;
Least attractive (and probably not needed).
Change the code to actually copy the pointer content into a new object.
squares.push_back(new SquareData(myMaze.squares[loopVar]));
Use of
squares.push_back(myMaze.squares[loopVar]);
in the copy constructor will lead to problems downstream.That will be vaild had the contents of squares been objects not pointers.
There are now two objects holding on to the pointers. Both willl try to call delete on the same pointer, which easily leads to undefined behavior.
You can fix the problem by:
Using a vector objects instead of a vector of pointers, or
Creating new objects from the heap and adding them to the new object.
squares.push_back(new SquareData(*myMaze.squares[loopVar]));
I am dealing with a task to create a troop of bunnies where they can multiply at each round. So I define a class of Bunny (individual), and then define a class of Troop with a vector point to different bunnies.
My problem is, every time I use new to create an object Bunny in a loop, it will come out an error says:
"Debug assertion failed!!...vector iterator not incrementable..."
Here is a sample of my code:
class Bunny {
private:
string sex;
string color;
string name;
int age;
public:
string getname() { return name;};
Bunny(); // constructor
};
class Troop {
private:
vector<Bunny *> bunpointer;
vector<Bunny *>::iterator it;
public:
void newbunny();
void multiply();
};
void Troop::newbunny() {
Bunny * bun; // pointer to the Bunny class
bun = new Bunny;
cout << "Bunny " << bun->getname() << " is born! \n";
bunpointer.push_back(bun);
}
void Troop::multiply() {
it = bunpointer.begin();
while(it!=bunpointer.end()) {
cout << (*it)->getname() << " gave a birth. ";
newbunny();
++it;
}
it = bunpointer.begin();
}
So if I create 5 bunnies at the beginning, and call function Troop::multiply, there should be 10 bunnies. An interesting observation is, the error will occur after 2 bunnies being born.
I think the problem may lie in the use of new to create new objects in a iterator loop. The new may somehow interrupt the iterator pointer *it. But I am not sure if this is the case, and if it really is, how to deal with this.
modified: so it is actually a problem of using push_back(), which will probably invalidate the iterator!!
Thank you in advance!!
1) Unless you have a reason to, your code does not need to use new at all. The code becomes easier, and no chance of memory leaks. Also, I don't see the need for an iterator member in the Troop class, unless you can justify the reason for it.
2) As to your immediate problem, just use a non-iterator reliant loop. In other words, a simple loop that goes from 0 to the number of current bunnies, less 1.
Here is an example:
#include <vector>
//...
class Troop {
private:
std::vector<Bunny> bunpointer;
public:
void newbunny();
void multiply();
};
void Troop::newbunny() {
bunpointer.push_back(Bunny());
}
void Troop::multiply() {
size_t siz = bunpoiner.size();
for (size_t i = 0; i < siz; ++i ) {
newbunny();
cout << (*it)->getname() << " gave a birth. ";
}
}
The newbunny() function simply creates a Bunny() using a default constructor and adds the item to the vector.
If you want to use a container that doesn't invalidate iterators when inserting items, then you can use a std::list as opposed to a std::vector.
It appears that you are trying to modify the std::vector while iterating over it. This is generally not a good idea, for a variety of reasons.
In particular, when you call newbunny() inside the iterator's loop, it is possible that the iterator you used to hold will be invalidated, because the vector may be resized during the push_back.
See this question for details.
As mentioned by others, the push_back() is your culprit, not the new.
One way to palliate would be this:
size_t const max(bunpointer.size());
for(size_t i(0); i < max; ++i)
{
cout << bunpointer[i]->getname() << " gave a birth. ";
newbunny();
}
This works because you are only adding new bunnies at the end of your existing vector. These new bunnies are not taken in account by the loop (max doesn't change because you call newbunny()...) and the [i] access makes use of the vector in its current state.
That loop would not work if you were deleting items...
As a side note: the name "bunpointer" is not very clear... it's not a pointer, it's a vector of pointers.