g++ -O2 flag giving segmentation fault - c++

The program below is a bst tree which works fine under unoptimized settings but produces a SIGSEGV under special circumstances. Since my debugging skills doesn't extend towards assembly, I can use some input to what is causing this error. Below is the full code so it can be reproduced. There is nothing fancy, a node struct is there to hold node data, a simple insert operation and a method to confirm the height of the tree.
#include <iostream>
#include <cstdlib>
using namespace std;
typedef struct avl_tree_node //node data
{
int data;
int balance{0};
avl_tree_node *left{NULL};
avl_tree_node *right{NULL};
avl_tree_node *parent{NULL};
}node;
class avl
{
private:
node *root;
int get_height(node *head) //calculates the height
{
if (head == NULL)
return -1;
int l_height = get_height(head->left);
int r_height = get_height(head->right);
if (l_height > r_height)
return l_height+1;
return r_height+1;
}
void unbalanced_insert(node *head, int item); //method definition for a simple insert
public:
avl(int data)
{
root->data = data;
root->parent = NULL;
root->left = NULL;
root->right = NULL;
}
int height() //gives the height
{
return get_height(root);
}
void unbalanced_insert(int item) //wrapper
{
unbalanced_insert(root, item);
}
};
void avl::unbalanced_insert(node *head, int item) //inserts node to the tree
{
//cout << "stepped" << endl;
if (item > head->data)
{
if (head->right == NULL)
{
head->right = (node*)malloc(sizeof(node));
head->right->data = item;
head->right->parent = head;
head->right->left = NULL;
head->right->right = NULL;
head->balance = 1;
return;
}
unbalanced_insert(head->right, item);
head->balance++;
return;
}
else
{
if (head->left == NULL)
{
head->left = (node*)malloc(sizeof(node));
head->left->data = item;
head->left->parent= head;
head->left->left = NULL;
head->left->right = NULL;
head->balance = -1;
return;
}
unbalanced_insert(head->left, item);
head->balance--;
return;
}
}
int main()
{
avl a(0);
for (int i = 1; i < 5; i++) //works until i < 4
{
a.unbalanced_insert(i);
}
cout << a.height() << endl;
return 0;
}
Under normal circumstances, I'd be happy that this works with unoptimized flags, but I have to build this with specific flags. One of such is the -O2 flag. The segmentation fault occurs between the avl a(0) object construction and the for loop inside main. The error also seems to be dependent on the boolean check of the for loop. This works fine if i < 4 and executed with: g++ avl.cpp -g -O2 -o program && ./program

One obvious problem, and it occurs on the very first function call in main, i.e. avl a(0):
root->data = data;
The root is uninitialized, thus the behavior is undefined.

I guess when instantiate the object of avl here.
avl a(0);
constructor of class as shown below is called.
avl(int data)
{
root->data = data;
root->parent = NULL;
root->left = NULL;
root->right = NULL;
}
But here I see root pointer is not allocated any memory

Related

How do I traverse a tree in-order and just get one value at a time instead of all values in C++

I'm trying to traverse a binary tree inorder and the problem I'm trying to solve requires me to return one value at a time. The problem with binary tree traversal is that you get everything at once using recursion.Don't get me wrong, I want everything but not at once.
What I tried implementing an array to store every value and then loop through and get each value.
But this too does not seem to work, CPP is complaining that "undefined reference to `IPAddressAnalyzer::nodesArray'"
Here's a snippet of my code:
struct node
{
int address;
int count;
node* left;
node* right;
};
class IPAddressAnalyzer{
private:
node* root;
static node *nodesArray;
int arrayIndex = 0;
void destroy_tree(node *leaf);
void insert(int ip, int count, node *leaf);
void inorder_print(node *leaf);
And here's where I'm trying to use the array:
void IPAddressAnalyzer::inorder_print(node* leaf)
{
if(leaf != NULL)
{
inorder_print(leaf->right);
nodesArray[arrayIndex].address = leaf->address;
nodesArray[arrayIndex].count = leaf->count;
updateArrayIndex();
inorder_print(leaf->left);
}
}
Here's where I create the array, access the elements in the array and try to write to a file.
//Create the array
tree->createArray(intCounter);
tree->inorder_print();
//Traverse tree and write to a file
int rank =1;
int counter = 0;
int valueHolder = 0;
int nodeIndex = 0;
while (rank<=n){
node element = nodesArray[nodeIndex];
printf("Popped ip: %s count: %d\n", IPAddressToString(element.address), element.count);
if(counter == 0) {
fprintf(outFileStream, "%d, %s, %d\n", rank, IPAddressToString(element.address), element.count);
valueHolder = element.count;
counter++;
}
else if(element.count == valueHolder)
{
fprintf(outFileStream, "%d, %s, %d\n", rank, IPAddressToString(element.address), element.count);
}
else{
rank++;
if(rank>n)
break;
fprintf(outFileStream, "%d, %s, %d\n", rank, IPAddressToString(element.address), element.count);
valueHolder = element.count;
}
nodeIndex++;
}
Please note that I set the size of the array size in the main function before I use it.
Or, to put it simply, here's an example of what I want;
#include <iostream>
using namespace std;
struct node
{
int value;
node *left;
node *right;
};
class btree
{
public:
btree();
~btree();
void insert(int key);
void destroy_tree();
void inorder_print();
private:
void destroy_tree(node *leaf);
void insert(int key, node *leaf);
void inorder_print(node *leaf);
node *root;
};
btree::btree()
{
root = NULL;
}
btree::~btree()
{
destroy_tree();
}
void btree::destroy_tree(node *leaf)
{
if(leaf != NULL)
{
destroy_tree(leaf->left);
destroy_tree(leaf->right);
delete leaf;
}
}
void btree::insert(int key, node *leaf)
{
if(key < leaf->value)
{
if(leaf->left != NULL)
{
insert(key, leaf->left);
}
else{
leaf->left = new node;
leaf->left->value = key;
leaf->left->left = NULL;
leaf->left->right = NULL;
}
}
else if(key >= leaf->value)
{
if(leaf->right != NULL)
{
insert(key, leaf->right);
}
else
{
leaf->right = new node;
leaf->right->value = key;
leaf->right->right = NULL;
leaf->right->left = NULL;
}
}
}
void btree::insert(int key)
{
if(root != NULL)
{
insert(key, root);
}
else
{
root = new node;
root->value = key;
root->left = NULL;
root->right = NULL;
}
}
void btree::destroy_tree()
{
destroy_tree(root);
}
void btree::inorder_print()
{
inorder_print(root);
cout << "\n";
}
void btree::inorder_print(node *leaf)
{
if(leaf != NULL)
{
inorder_print(leaf->left);
cout << leaf->value << ",";
inorder_print(leaf->right);
}
}
int main(){
//btree tree;
btree *tree = new btree();
tree->insert(10);
tree->insert(6);
tree->insert(14);
tree->insert(5);
tree->insert(8);
tree->insert(11);
tree->insert(18);
tree->inorder_print();
delete tree;
}
This produces the following output at once:
5,6,8,10,11,14,18,
How can I get 5, then 6, then 8 etc, but each at a time, instead of all at once?
Any help offered will be appreciated!
CPP is complaining that "undefined reference to IPAddressAnalyzer::nodesArray"
This is probably because nodesArray is a static member variable, but you never declared storage for it. In some .cpp file, preferably one related to IPAddressAnalyzer, you should add the following line:
node *IPAddressAnalyzer::nodesArray;
But maybe just making it a non-static member would be even better.
I suggest you make use of the standard library instead of implementing your own tree structure, and use std::map and/or std::set instead. Your example of what you want can be rewritten like so:
#include <iostream>
#include <set>
int main(){
std::set<int> tree;
tree.insert(10);
tree.insert(6);
tree.insert(14);
tree.insert(5);
tree.insert(8);
tree.insert(11);
tree.insert(18);
for (auto &element: tree) {
std::cout << element << ',';
}
std::cout << '\n';
}

Segmentation fault in passing pointer to a linked list

Hello fellow programmers, the below code gives segmentation fault. This code aims to insert an element at the end of a linked list. I tried using print statements to debug it. I think the error is in passing the linked list pointer to insert() function. Please tell me how can I correct it. Thanks in advance.
Below is the code:
#include <iostream>
using namespace std;
class node {
public:
int data;
node *next;
node(int data) {
this->data = data;
this->next = NULL;
}
};
class linked_list {
public:
node *head;
linked_list() {
this->head = NULL;
}
};
void insert(node **head, int data);
void print(linked_list *L);
int main() {
int N;
linked_list *A = new linked_list();
cout << "N: ";
cin >> N;
for(int i=0; i<=N-1; i++) {
int t;
cin >> t;
insert(&(A->head), t);
}
print(A);
return 0;
}
void insert(node **head, int data) {
node *temp = new node(data);
if(*head == NULL) {
*head = temp;
return;
} else {
node *t = *head;
while(t->next != NULL) {
t=t->next;
}
t->next = temp;
return;
}
}
void print(linked_list *L) {
node * t = L->head;
while(t!=NULL) {
cout << t->data << " ";
t = t->next;
}
return;
}
main.cpp:42:14: error: using the result of an assignment as a
condition without parentheses [-Werror,-Wparentheses]
if(*head = NULL) {
~~~~~~^~~~~~
main.cpp:42:14: note: place parentheses around the assignment to
silence this warning
if(*head = NULL) {
^
( )
main.cpp:42:14: note: use '==' to turn this assignment into an
equality comparison
if(*head = NULL) {
^
==
1 error generated.
You're using assignment where you intended to do a comparison.

Implementing a recursive Void function (Finding height of Binary Search Tree)

I need to implement a void function that computes the height of each node in a binary tree and stores it in each node. I've found a few solutions online that are recursive in nature but they return int. Examples include (https://www.geeksforgeeks.org/write-a-c-program-to-find-the-maximum-depth-or-height-of-a-tree/). The difference between the model answer, besides that it is not a void function, is that it also does not store the height in each node.
This is my attempt at the solution, but I can't seem to get the code to work, nor refit the model answer to recursively apply in a void function. When I run my code in the helper code to test, it doesn't even show any output.
void computeHeight(Node *n) {
Node* ltraverser = n;
Node* rtraverser = n;
int lheight = 0;
int rheight =0;
if (n == NULL) {
n->height = 0;
}
while (ltraverser->left != NULL) {
ltraverser = ltraverser->left;
lheight += 1;
}
while (rtraverser->right != NULL) {
rtraverser = rtraverser->right;
lheight += 1;
}
if (lheight > rheight) {
n->height = lheight;
}
else {
n->height = rheight;
}
computeHeight(n->left);
computeHeight(n->right);
}
For reference:
The starter code below defines a class called "Node" that has two child pointers ("left" , "right") and an integer "height" member variable. There is also a constructor Node() that initializes the children to nullptr and the height to -1.
/*
The height of a node is the number of edges in
its longest chain of descendants.
Implement computeHeight to compute the height
of the subtree rooted at the node n. Note that
this function does not return a value. You should
store the calculated height in that node's own
height member variable. Your function should also
do the same for EVERY node in the subtree rooted
at the current node. (This naturally lends itself
to a recursive solution!)
Assume that the following includes have already been
provided. You should not need any other includes
than these.
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <string>
You have also the following class Node already defined.
You cannot change this class definition, so it is
shown here in a comment for your reference only:
class Node {
public:
int height; // to be set by computeHeight()
Node *left, *right;
Node() { height = -1; left = right = nullptr; }
~Node() {
delete left;
left = nullptr;
delete right;
right = nullptr;
}
};
*/
For testing the code
// This function prints the tree in a nested linear format.
void printTree(const Node *n) {
if (!n) return;
std::cout << n->height << "(";
printTree(n->left);
std::cout << ")(";
printTree(n->right);
std::cout << ")";
}
Node *n = new Node();
n->left = new Node();
n->right = new Node();
n->right->left = new Node();
n->right->right = new Node();
n->right->right->right = new Node();
computeHeight(n);
printTree(n);
std::cout << std::endl << std::endl;
printTreeVertical(n);
delete n;
n = nullptr;
return 0;
}
Instead of returning node height just recurisvely call computeHeight on left and right nodes, then store maximum height in node structure.
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <string>
#include <algorithm>
class Node {
public:
int height;
Node *left, *right;
Node() { height = -1; left = right = nullptr; }
~Node() {
delete left;
left = nullptr;
delete right;
right = nullptr;
}
};
void computeHeight(Node *node) {
if (node == nullptr) {
return;
}
computeHeight(node->left);
computeHeight(node->right);
int leftHeight = -1;
int rightHeight = -1;
if (node->left != nullptr) {
leftHeight = node->left->height;
}
if (node->right != nullptr) {
rightHeight = node->right->height;
}
node->height = std::max(leftHeight, rightHeight) + 1;
}
void printNode(Node *n, int level = 0) {
if (n == nullptr) {
return;
}
std::cout << std::string(level * 2, ' ') << "Height = " << n->height << "\n";
printNode(n->left, level + 1);
printNode(n->right, level + 1);
}
int main() {
Node *n = new Node();
n->left = new Node();
n->right = new Node();
n->right->left = new Node();
n->right->right = new Node();
n->right->right->right = new Node();
computeHeight(n);
printNode(n);
}
Your mistake is on the following part and because of this you program exits without showing the error
if (n == NULL) {
n->height = 0;
}
When n is NULL; you should not try to access n->height. Replace it as follows and your code will work:
if (n == NULL) {
return;
}
Also, as the other answer mentioned, when you want to compute height recursively, you don't need a while loop just use the following recursive formula:
Height(n) = 1 + max(Height(n->left), Height(n->right))
Also, for consistency reasons usually the height of NULL subtree is defined to be -1. This allows the recursive formula to work properly.
Word of advice: In order to debug any program, an easy way is to just print messages before and after function calls and/or certain lines. This way by checking which messages are not printed, you can quickly pinpoint which functions/lines are causing a problem and then investigate them.

Segmentation fault on recursion function c++

I was working on Pre-order traverse Binary Tree algorithm. But I meet with Segmentation fault:11 error. The codes are shown as follow.
I want to know why this error happens. By the way, I have tried non-recursion algorithm preorder(),segmentation fault still happen.
The environment:
macOS, clang-800.0.38
struct Node{
char val;
Node* left;
Node* right;
};
void preorder(Node *T){
if(T!=NULL){
cout << T->val;
preorder(T->left);
preorder(T->right);
}
}
int main(){
Node *T = (Node *)malloc(sizeof(Node));
Node *p = T;
p->val = 'A';
p->left = (Node *)malloc(sizeof(Node));
p->left->val = 'B';
p->right = (Node *)malloc(sizeof(Node));
p->right->val = 'C';
preorder(T);
return 0;
}
You need to initialize left and right member variables of your nodes to null pointers.
Anyway, if you use C++, use C++ and not C constructs. This is an exemplary C++14 version of your code:
#include <iostream>
#include <memory>
struct Node{
Node(char a) : val(a) { };
char val;
std::unique_ptr<Node> left, right;
};
void preorder(Node* p) {
if (p) {
std::cout << p->val;
preorder(p->left.get());
preorder(p->right.get());
}
}
int main() {
auto root = std::make_unique<Node>('A');
root->left = std::make_unique<Node>('B');
root->right = std::make_unique<Node>('C');
preorder(root.get());
}
The problem is left and right of your child nodes are not initialized to NULL. Due to previous value stored in that memory location the program is encountering non-null value in your if(T!=nullptr) statement and executing the if block.
struct Node{
char val;
Node* left;
Node* right;
};
void preorder(Node *T){
if(T!=nullptr){
cout << T->val;
preorder(T->left);
preorder(T->right);
}
}
int main(){
Node *T = (Node *)malloc(sizeof(Node));
Node *p = T;
p->val = 'A';
p->left = (Node *)malloc(sizeof(Node));
p->left->val = 'B';
p->left->left = nullptr; //Initialize to NULL
p->left->right = nullptr; //Initialize to NULL
p->right = (Node *)malloc(sizeof(Node));
p->right->val = 'C';
p->right->left = nullptr; //Initialize to NULL
p->right->right = nullptr; //Initialize to NULL
preorder(T);
return 0;
}

print doubly linked list - no result

I am new to c++ and programming in general. I am trying to implement a doubly linked list. I think the list is created successfully, but I am having trouble printing the list out entirely. Can you please let me know what's wrong with my printListForward method below? My code is not complete yet. Would really appreciate any tips and suggestions as well.
#include "MagicSquare.hpp"
#include <iostream>
class MagicSquaresList{
private:
struct MagicSquaresNode{
int nodeIndex;
MagicSquaresNode *pleft;
MagicSquaresNode *pright;
MagicSquaresNode *pup;
MagicSquaresNode *pdown;
};
MagicSquaresNode *head;
MagicSquaresNode *tail;
public:
MagicSquaresList (){
head = NULL;
tail = NULL;
}
int getListLength(){
int length = 1;
MagicSquaresNode *temp = new MagicSquaresNode;
temp = head;
if(isEmpty()){
return 0;
}else{
while(temp != tail){
length++;
temp = temp->pright;
}
}
return length;
}
bool isEmpty(){
return head == NULL;
}
void appendToEnd(int val){
MagicSquaresNode *newNode = new MagicSquaresNode;
newNode->nodeIndex = val;
if(isEmpty()){
tail = newNode;
} else {
tail->pright = newNode;
newNode->pleft = tail;
}
tail = newNode;
}
void printListForward() {
MagicSquaresNode *ptr = head;
while(ptr != tail){
std::cout << ptr->nodeIndex << " ";
ptr = ptr->pright;
}
std::cout << std::endl;
}
};
int main(){
/*********** temporary *****************/
int matrixSize, listSize;
matrixSize = 3;
listSize = matrixSize * matrixSize;
/****************************************/
MagicSquaresList list1;
for (int i = 1; i <= listSize; i++){
list1.appendToEnd(i);
}
list1.printListForward();
std::cout << list1.getListLength() << std::endl;
return 0;
}
You need to set the head.
void appendToEnd(int val){
MagicSquaresNode *newNode = new MagicSquaresNode;
newNode->nodeIndex = val;
if(isEmpty()){
tail = newNode;
head = newNode;
} else {
tail->pright = newNode;
newNode->pleft = tail;
}
tail = newNode;
}
Just a few comments. First you want to use proper indents. For beginner it is important to learn to write a simple Makefile. In your case, I wrote one for you.
Makefile:
1 bin_PROGRAMS=doublelink
2 GCCLIBDIR= /usr/local/lib64
3 CXXFLAGS=-g -std=c++11
4 CC=g++
5 LDFLAGS=-L$(GCCLIBDIR)
6
7 all : $(bin_PROGRAMS)
8
9 doublelink : doublelink.o
10 $(CC) $(CXXFLAGS) -o $# $^ $(LDFLAGS)
For your source code I did simple editing and named your file: doublelink.cpp:
//#include "MagicSquare.hpp"
#include <iostream>
using namespace std;
class MagicSquaresList{
private:
struct MagicSquaresNode {
MagicSquaresNode(int ni) : nodeIndex(ni), pleft(0), pright(0), pup(0), pdown(0) { }
int nodeIndex;
MagicSquaresNode *pleft;
MagicSquaresNode *pright;
MagicSquaresNode *pup;
MagicSquaresNode *pdown;
};
MagicSquaresNode *head;
MagicSquaresNode *tail;
public:
MagicSquaresList () {
head = 0;
tail = 0;
}
int getListLength(){
MagicSquaresNode *temp = head;
if (temp == 0) {
return 0;
}
int length = 0;
while (temp != 0) {
++length;
temp = temp->pright;
}
return length;
}
bool isEmpty(){
return head == 0;
}
void appendToEnd(int val){
MagicSquaresNode *newNode = new MagicSquaresNode(val);
if (tail == 0) {
head = newNode;
}
else {
tail->pright = newNode;
newNode->pleft = tail;
}
tail = newNode;
}
void printListForward() {
MagicSquaresNode *ptr = head;
while (ptr != 0) {
//cout << ptr << endl;
std::cout << ptr->nodeIndex << " ";
ptr = ptr->pright;
}
std::cout << std::endl;
}
};
int main(){
/*********** temporary *****************/
int matrixSize, listSize;
matrixSize = 3;
listSize = matrixSize * matrixSize;
/****************************************/
MagicSquaresList list1;
for (int i = 1; i <= listSize; i++){
list1.appendToEnd(i);
}
list1.printListForward();
std::cout << list1.getListLength() << std::endl;
return 0;
}
With both file in the directory, you type
make
a binary file doublelink will appear in your directory.
you run this program by typing its name:
$ doublelink
1 2 3 4 5 6 7 8 9
9
But with all these efforts. You should never need to implement double linked list. You should use the C++ standard library and customize the data type for your purpose. The std::list is implemented as double linked list. Please read the document at http://www.cplusplus.com/reference/list/list/. You should create your structure of interest by
list<MagicSquare> myfancySquareList;
myfancySquareList.push_back(MagicSquare(somevalue));
Your double linked list is also missing the destructor, and you are having memory leak. There are many other missing things from your implementation which is usually covered by a text book of several hundred pages. Hope this get you started. When you have trouble, you can run your program in debug mode: gdb doublelink. You can step through it and figure out where is your problem. Your initial problem is a segmentation fault. Try to run your original program and see where it terminate.