c++ elusive segmentation fault - c++

Im working on this bit of code and I keep getting a segmentation fault. For the life of me I cant figure out why, I know a segmentation fault is when you try to follow a null pointer, but the thing is, in my code "u->previous" isnt null, neither is "u", I checked. If I change the condition in the while loop to (u != NULL), it will iterate twice before faulting on "u->isGreen", Once again, I checked every iteration to see if u was null.
int extractOptimalPath() {
Node *u = nodes[NUM_NODES - 1];
int i = 0;
while (u != NULL) {
cout << i << endl;
u->isGreen = true;
u = u->previous;
i++;
}
return 0;
}
"nodes" is an array of pointers to actual Node objects. I know for sure that the "u->previous" exists in my nodes and "isGreen" is initialized to false;
Heres the Node class, in case you want to see that:
class Node {
public:
GLfloat x, y, z;
int numLinks;
Node *link1;
Node *link2;
GLfloat distance;
Node *previous;
bool isGreen;
Node(GLfloat x, GLfloat y, Node *link1, Node *link2);
Node(GLfloat x, GLfloat y, Node *link1);
Node();
Node(GLfloat x, GLfloat y);
~Node();
bool dijkstra(Node* graph[], Node *source, Node *target); //returns true if a path to target is found
int dist(Node *n1, Node *n2);
int extractOptimalPath(Node* graph[]);
};
What could be causing the seg fault?

That error isn't just for null pointers, it is a pointer that points to anything invalid. That can be null, but it can also be memory that was freed.

I don't see a copy constructor in Node, while I see pointers and a destructor. So you violated the Rule of Three.
As a result, if you accidently copy a Node, that copy's destructor will result in effects you see now.
Update:
To quickly test for this, add a private copy constructor to your Node class, like this:
class Node {
...
private:
Node(const Node&);
};
If you get compiler errors now, you are making copies. The compiler will point you to the locations where that happens.

You don't need to have a NULL pointer to have a Segmentation Fault, it happens every time you access memory out of your allowed scope. Check the thread What is a segmentation fault?.
Your code isn't sufficient to say what causes a segfault. Most likely u->previous in one of your nodes points to some more or less random place in memory, but it's just a guess.

My guess is that in your constructor of a Node object, the previous pointer is never set to NULL at any point. You should have a point when previous is set to NULL (in your actual code, don't assume the code does this for you automatically). Also, as a tip, try using gdb to step through your code. Another tip, valgrind is usually used to consult memory leaks, but I've used it to successfully pinpoint segfaults as well.

Related

What exactly is causing my node class with a vector housing the pointers of the class to cause segmentation faults?

Currently I'm just starting off with creating nodes for my tree. The idea I had in mind was to simply create something like this:
class Node
{
private:
int key_;
std::vector< Node * > child_;
public:
Node(int key)
: key_(key), child_()
{
}
Node * get_child(int key) const
{
return child_[key];
}
};
Nothing too fancy, right?
Inside the main, I call all the header files and have initialized the whole entire thing like this
Node child(0);
What causes some frustration right now is when I try to simply just check if everything in my node is truly initialized. All I'm doing in the main is this.
std::cout << node.get_child(0) << std::endl;
The dreaded segmentation fault error comes up which means that the memory allocation of the vector is off. My question is this, if this is actually what's happening, what in my code is wrong so far? If it is not, please clarify on what exactly in my class template is wrong.
In the constructor for Node, you set the internal key value, and construct an empty vector. You don't have any code shown that adds anything to the vector, and trying to access element 0 of an empty vector results in Undefined Behavior (a crash, in your case).
You probably want something like child(1) (to create one node in the vector), child(key + 1, nullptr) (to create null node pointers so that elements in the 0..k inclusive range are valid) or a loop in the constructor to set actual nodes into the vector.

Initializing Vector of Structs in Constructor C++

in Class.h
Struct Node
{
int ID;
int position;
}
In class Class.cpp I am initializing vector of structs which leads to core dump error
Class::Class(const branch& branches):mybranches(branches)
{
for (const auto & branch:mybranches)
{
Node* node
node->ID= branch->ID
node->position= branch->position
mynodesvector.push_back(std::move(node));
}
}
However initializing it like this leads to no error
Class::Class(const branch& branches):mybranches(branches)
{
for (const auto & branch:mybranches)
{
Node node
node.ID= branch->ID
node.position= branch->position
mynodesvector.push_back(&node);
}
}
I want to know what is the reason for the core dump error with initializing it as pointer to struct.
You do not create/allocate an object to which node* shall point; so dereferencing node leads to undefined behaviour;
Node* node;
node->ID= branch->ID; // UB here...
However, allocating an object like
Node* node = new Node();
node->ID= branch->ID;
...
should work.
In your second example, you define a Node-object (and not just a pointer to it). So at least accessing its members is save.
Node node; // defines a Node-object.
node.ID= branch->ID; //save
node.position= branch->position; // save
Note, however, that you push_back a pointer to an object with block scope; when you dereference this pointer later, the actual object will be out of scope and you get undefined behaviour then.
mynodesvector.push_back(&node);
I'd suggest to have a look at std::shared_ptr<Node>.
In addition to the answer of #Stefan Lechner:
The version which throws no direct error has a bug which is likely to blow up whenever you try to modify the values in the mynodesvector:
you initialize a struct on the stack and then push its address into a vector. Once an iteration of the for loop has terminated, the Node instance is destructed, but you still have the pointer to it in the vector.
for (const auto & branch:mybranches)
{
{
Node node
node.ID= branch->ID
node.position= branch->position
mynodesvector.push_back(&node);
}
// here, Node is dead, but the pointer to it lives on.
}
In order to find bugs like that that escape your code control I recommend enabling compiler warnings and using appropriate sanitizers.

Process returned -1073741819 (0xC0000005) problem on insertion of value

I am trying to create an AVL Tree and insert a node into it. Whenever I try to add a data value ın the tree node, my program crashes and returns the value 0xC0000005. This is how I have introduced the data item in the header file:
class AVLTreeNode
{
public:
int data;
AVLTreeNode();
virtual ~AVLTreeNode();
AVLTreeNode(int d, AVLTreeNode *leftChild, AVLTreeNode *rightChild);
AVLTreeNode *leftc;
AVLTreeNode *rightc;
int height;
}
Whenever I try to run the following lines of the code in the insert function, I get the crash.
AVLTreeNode *nw = NULL ;
nw->data = v;
I don't know what I'm doing wrong, please help me.
The return code of 0xC0000005 means STATUS_ACCESS_VIOLATION. (You can find this and other NT status codes on MSDN: NTSTATUS Values.) The error happens because NULL is outside the range of valid addresses for your program. Before dereferencing a pointer variable, you must assign it the address of a valid object. For example:
AVLTreeNode* nw = new AVLTreeNode{};
nw->data = v;
AVLTreeNode *nw = NULL;
This line of code sets nw to be a null pointer, in other words, it doesn’t point at anything. Trying to dereference a null pointer will result in undefined behaviour. You need to allocate memory for an AVLTreeNode object, and then get nw to point at it.
What you need instead is this, which allocates memory and points nw at it:
AVLTreeNode *nw = new AVLTreeNode;
And remember, whenever you allocate memory with new you need to deallocate it when you're finished with it:
delete nw;

C++ Binary Tree recursive destructor issue

I made a binary tree class which holds:
int value, BinaryTree* left, BinaryTree* right.
class BinaryTree {
private:
int value;
BinaryTree* left;
BinaryTree* right;
bool isVisited;
public:
BinaryTree();
BinaryTree createComplete(int n);
~BinaryTree();
}
My destructor is :
BinaryTree::~BinaryTree() {
delete left;
delete right;
}
When running in clion it works perfectly, but in my terminal I get
a segfault (core dumped). Everywhere I looked people claimed that this should be the destructor. Any elaboration would help!
I am not a stackoverflow expert , I updated my ~BinaryTree function to still gets a segfault :
BinaryTree::~BinaryTree() {
if (right != NULL) {
delete right;
}
if (left != NULL) {
delete left;
}
}
First of all your current implementation is not that of a complete tree.
It is a node, thus I suggest renaming it to BinaryTreeNode and using it to construct a new class BinaryTree, that keeps track of the root and allows you to recursively deallocate the tree.
Having said that your destructor most likely segfaults because you are blindly attempting to delete a pointer.
First make sure you initialize left and right to nullptr.
Then you do if(left != nullptr) { delete left }
Without seeing your constructor, I assume you don't initialize your node's children to NULL. That might mean that the uninitialized nodes left and right at the bottom leaves have a random value in them. When the destructor runs, it will try to free the memory that the random garbage in the nodes point to.
Try initializing your child nodes to NULL when ctoring nodes, then making a check for it like monoceres suggested. It will also be good to set the pointer to NULL after delete to avoid situation of erronous double delete
So after debugging I noticed that the every right child is loosing it's nodes , which while going in a pre order traversal is fine , but when deleting it casuing the problem , thanks for the help every one !

Memory Management Confusion C++

I'm having trouble understanding some basic memory management principles in C++. This code is part of a loop that is part of a function that reads in a maze file into a 2D vector.
According to Valgrind, the following code is causing memory leaks...
Note that t is a MazeNode object and verts is a vector within the t class that holds pointers to node objects (not to be confused with MazeNode objects):
node* top = new node(TOP, rowCount, i, t.type);
node* bot = new node(BOTTOM, rowCount, i, t.type);
node* left = new node(LEFT, rowCount, i, t.type);
node* right = new node(RIGHT, rowCount, i, t.type);
t.verts.push_back(top);
t.verts.push_back(bot);
t.verts.push_back(left);
t.verts.push_back(right);
temp.push_back(t);
top = NULL;
bot = NULL;
left = NULL;
right = NULL;
delete top;
delete bot;
delete left;
delete right;
Initially I did not set each of the pointers to NULL before deleting them, but would get allocation errors. So I just set them to NULL and my code works. I guess I'm just really confused why this would cause memory leaks and why I would need to set the pointers to NULL. There is probably a way easier non-pointer way to do this, but maybe this problem will help me understand memory management better.
Thanks everyone.
EDIT: Here's the MazeNode class (which is what 't' is) (also excuse my lazyness in writing this class, making everythign public like a struct)
class MazeNode
{
public:
void setType(char c);
char getChar();
NodeType type;
vector<Direction> visitedFrom;
vector<node*> verts;
};
And the node class:
class node
{
public:
node();
node(Direction d, int r, int c, NodeType t);
~node(); //empty definition
node(const node* n);
node& operator=(const node& n);
void addAdj(node* a, int w);
void printAdj() const;
string direction() const;
void print() const;
bool operator<(const node& n) const;
int distance; //from start
bool visited;
node* prev;
vector<Edge> adj;
Direction dir;
int row, col;
NodeType type;
};
EDIT2: Thanks everyone. I understand the problem now. I changed my vectors of pointer objects so that I wasn't using pointers anymore.
Prior to adding the null assignment, your code had a problem different (worse) than a memory leak: storing and probably also using a stray pointer, that is, a pointer pointing into de-allocated memory.
Making it a memory leak by adding the null assignment makes it better, but not much.
The real solution is not to keep any pointers anywhere after you have called delete on them.
That is, do not push_back or do not delete here.
You are placing the pointers into a container, then deleting the pointers. When your code later tries to use those pointers they are invalid and cause a crash.
By setting the pointers to NULL before you delete them, you end up not deleting them at all - deleting a NULL pointer doesn't do anything. But now there's nothing to delete the objects later, and you get a memory leak.
You need to find some spot in the code where you're not using the pointers anymore, and delete them there.
Edit: Of course I should have mentioned that a smart pointer such as std::shared_ptr eliminates this hassle altogether, because it deletes the object automatically.
You are setting the values to NULL before deleting them, so you are trying to delete NULL and nothing is being deleted. Try moving the delete calls above the NULL calls.
This confusion is exactly why I create a macro for these kind of things:
#define delobj(obj) (delete obj, obj = NULL)
And you would use it like this:
delobj(top);
delobj(bot);
delobj(left);
delobj(right);
The error is using the vector of pointers. According to you, verts is this:
vector<node*> verts;
But what it should be is this:
vector<node> verts;
In the first case, when you push_back() the pointer, that's OK, but when you pop_back or otherwise re-size the vector, the pointer is the "contents" of the vector, and is de-allocated, but not what the pointer points to, which is the node. Hence the node leaks. But in the second case, the node is "part" of the vector, and is allocated/deallocated as part of re-sizing the vector.
Your pattern here probably indicates a Java/C# background, as "new-ing" into a container is very very common in those languages, but to do that in C++, you need a container of smart pointers (like vector<shared_ptr<node>> or something), which is probably beyond the scope of the question. But in those languages, every reference to a reference type is a "smart pointer" (more or less) and so this is done automatically. C++ isn't like that.
You either need to change your code to use a vector<node> (and change how you're pushing back on to it) or you need to explicitly de-allocate your nodes when the vector shrinks.
Change to:
delete top;
delete bot;
delete left;
delete right;
top = NULL;
bot = NULL;
left = NULL;
right = NULL;
And it should work.