Find the cause of 'SEGV on unknown address', cause by READ access - c++

I'm writing a Splay Tree implementation. Code compiles just fine in VS, but the testing system fails with DEADLYSIGNAL.
The specific input for testing is:
search 66
min
max
set 1 20
print
Here is the full code:
#include <iostream>
#include <sstream>
#include <stack>
#include <queue>
#include <cmath>
struct Node
{
int64_t key;
std::string value;
Node* left, * right, * parent;
Node(const int64_t& k) : key(k), left(nullptr), right(nullptr), parent(nullptr) {}
Node(const int64_t& k, const std::string& v, Node* p) : key(k), value(v),
left(nullptr), right(nullptr), parent(p) {}
};
class SplayTree
{
Node* root;
size_t size;
bool isRight(Node* node)
{
if (node && node->parent)
if (node->parent->right == node)
return true;
else
return false;
}
std::pair<int, Node*> Find(const int64_t& key)
{
Node* node = root;
while (node)
{
if (node->key == key)
return { 2, node };
else if (node->key > key)
if (node->left)
node = node->left;
else
return { 0, node };
else if (node->key < key)
if (node->right)
node = node->right;
else
return { 1, node };
}
}
void Merge(Node* left, Node* right)
{
if (!left && !right)
root = nullptr;
else if (!left)
{
root = right;
right->parent = nullptr;
}
else if (!right)
{
root = left;
left->parent = nullptr;
}
else
{
left = Max(left);
left->parent = nullptr;
left->right = right;
right->parent = left;
}
}
void rotateL(Node* node)
{
Node* p = node->parent;
Node* r = node->right;
if (p != nullptr)
if (p->left == node)
p->left = r;
else
p->right = r;
Node* temp = r->left;
r->left = node;
node->right = temp;
node->parent = r;
r->parent = p;
if (temp != nullptr)
temp->parent = node;
}
void rotateR(Node* node)
{
Node* p = node->parent;
Node* l = node->left;
if (p != nullptr)
if (p->left == node)
p->left = l;
else
p->right = l;
Node* temp = l->right;
l->right = node;
node->left = temp;
node->parent = l;
l->parent = p;
if (temp != nullptr)
temp->parent = node;
}
void Zig(Node* node)
{
!isRight(node) ?
rotateR(node->parent) : rotateL(node->parent);
}
void ZigZig(Node* node, bool side)
{
if (side)
{
rotateL(node->parent->parent);
rotateL(node->parent);
}
else
{
rotateR(node->parent->parent);
rotateR(node->parent);
}
}
void ZigZag(Node* node, bool side)
{
if (side)
{
rotateL(node->parent);
rotateR(node->parent);
}
else
{
rotateR(node->parent);
rotateL(node->parent);
}
}
void Splay(Node* node)
{
while (node->parent != nullptr)
{
if (node->parent == root)
Zig(node);
else if (!isRight(node) && !isRight(node->parent))
ZigZig(node, 0);
else if (isRight(node) && isRight(node->parent))
ZigZig(node, 1);
else if (!isRight(node) && isRight(node->parent))
ZigZag(node, 0);
else
ZigZag(node, 1);
}
root = node;
}
std::string printNode(Node* node)
{
std::string result;
result += '[' + std::to_string(node->key) + ' ' + node->value;
if (node->parent)
result += ' ' + std::to_string(node->parent->key);
result += ']';
return result;
}
Node* Max(Node* node)
{
Node* temp = node;
if (temp)
{
while (temp->right)
temp = temp->right;
Splay(temp);
return temp;
}
else
return nullptr;
}
Node* Min(Node* node)
{
Node* temp = node;
if (temp)
{
while (temp->left)
temp = temp->left;
Splay(temp);
return temp;
}
else
return nullptr;
}
public:
Node* getRoot() { return root; }
SplayTree() : root(nullptr), size(0) { }
SplayTree(uint64_t key)
{
root = new Node(key);
size = 1;
}
~SplayTree()
{
if (root)
{
std::stack<Node*> toDelete;
toDelete.push(root);
while (!toDelete.empty())
{
Node* node = toDelete.top();
if (node->left)
{
toDelete.push(node->left);
node->left = nullptr;
}
else if (node->right)
{
toDelete.push(node->right);
node->right = nullptr;
}
else
{
toDelete.pop();
delete node;
}
}
}
}
bool Add(const int64_t& key, const std::string& value)
{
if (!root)
{
root = new Node(key, value, nullptr);
size++;
return true;
}
else
{
std::pair<int, Node*> result = Find(key);
if (result.first == 2)
return false;
else if (result.first == 0)
{
result.second->left = new Node(key, value, result.second);
Splay(result.second->left);
size++;
return true;
}
else
{
result.second->right = new Node(key, value, result.second);
Splay(result.second->right);
size++;
return true;
}
}
}
std::string Search(const int64_t& key)
{
if (root)
{
std::pair<int, Node*> result = Find(key);
if (result.first == 2)
{
Splay(result.second);
return "1 " + result.second->value;
}
Splay(result.second);
}
return "0";
}
Node* Min() { return Min(root); }
Node* Max() { return Max(root); }
bool Set(const int64_t& key, const std::string& value)
{
std::pair<int, Node*> result = Find(key);
if (result.first == 2)
{
result.second->value = value;
Splay(result.second);
return true;
}
else
return false;
}
bool Delete(const int64_t& key)
{
if (!root)
return false;
std::pair<int, Node*> result = Find(key);
if (result.first == 2)
{
Splay(result.second);
Node* subL = result.second->left;
Node* subR = result.second->right;
Merge(subL, subR);
delete result.second;
size--;
return true;
}
return false;
}
std::string Print()
{
std::string result;
std::queue<Node*> toPrint;
toPrint.push(root);
size_t counter = size;
size_t space = 0;
size_t i = 0;
while (!toPrint.empty())
{
Node* node = toPrint.front();
toPrint.pop();
space++;
if (node)
{
result += printNode(node);
toPrint.push(node->left);
toPrint.push(node->right);
counter--;
}
else
{
result += "_";
toPrint.push(nullptr);
toPrint.push(nullptr);
}
if (space == pow(2, i))
{
result += "\n";
if (counter != 0)
{
i++;
space = 0;
}
}
else
result += " ";
if (counter == 0 && space == pow(2, i))
break;
}
return result;
}
};
int main()
{
std::string data;
std::getline(std::cin, data, '\0');
data += '\n';
std::istringstream is(data);
std::ostringstream os;
SplayTree tree;
int64_t key;
std::string command, value;
bool empty = false;
while (is >> command)
{
if (command.empty())
{
empty = true;
}
if (command == "add" && is.peek() != '\n'
&& is >> key && is.peek() != '\n' && is >> value && is.peek() == '\n')
{
if (!tree.Add(key, value))
os << "error" << std::endl;
}
else if (command == "set" && is.peek() != '\n'
&& is >> key && is.peek() != '\n' && is >> value && is.peek() == '\n')
{
if (!tree.Set(key, value))
os << "error" << std::endl;
}
else if (command == "delete" && is.peek() != '\n'
&& is >> key && is.peek() == '\n')
{
if (!tree.Delete(key))
os << "error" << std::endl;
}
else if (command == "search" && is.peek() != '\n'
&& is >> key && is.peek() == '\n')
{
os << tree.Search(key) << std::endl;
}
else if (command == "min" && is.peek() == '\n')
{
Node* temp = tree.Min();
if (temp)
{
os << temp->key << " "
<< temp->value << std::endl;
}
else
os << "error" << std::endl;
}
else if (command == "max" && is.peek() == '\n')
{
Node* temp = tree.Max();
if (temp)
{
os << temp->key << " "
<< temp->value << std::endl;
}
else
os << "error" << std::endl;
}
else if (command == "print" && is.peek() == '\n')
{
os << tree.Print();
}
else
{
if (!empty)
os << "error" << std::endl;
}
}
std::cout << os.str();
return 0;
}
VS debugger tells me nothing on what causes this error. Sanitazier describes it as read fault, but I can't figure out in which function exactly it happens.
Also, full Sanitizer output:
AddressSanitizer:DEADLYSIGNAL
=================================================================
==26100==ERROR: AddressSanitizer: SEGV on unknown address 0x00000004 (pc 0x08164c7a bp 0xbff0f8d8 sp 0xbff0f420 T0)
==26100==The signal is caused by a READ memory access.
==26100==Hint: address points to the zero page.
Hope someone helps. Thank you in advance.

Since this shows up in search results:
Some part of you code (which you'll find out when you see the full ASan error) is creating an invalid address 0x4 which ASan wants to see the memory of.
It could be say an int accidentally cast to a pointer or an intentional cast like say
auto p = (int*)4;
See full error and the stack trace in it.
Derived class offset calculation in boost::serialization. Is it valid?

Related

I'm having a segmentation error when I use a dataset of 1000 key values and for some reason the the AVL rotations don't happen around the node

#include "BST.h"
#include "AVL.h"
#include <iostream>
AVLTree::AVLTree() {
}
int AVLTree::max(int a, int b) {
return (a > b)? a : b;
}
int AVLTree::height(std::shared_ptr<BSTNode>N) const {
if (N == nullptr){
return 0;
}
return N->height_;
}
void AVLTree::fixHeight(std::shared_ptr<BSTNode>& N) {
auto h1 = height(N->left_);
auto h2 = height(N->right_);
N->height_ = (h1 > h2 ? h1 : h2) + 1;
}
int AVLTree::getBalance(std::shared_ptr<BSTNode> N) {
if (N == nullptr)
return 0;
return height(N->left_) - height(N->right_);
}
std::shared_ptr<BSTNode> AVLTree::rightRotate(std::shared_ptr<BSTNode>n){
std::shared_ptr<BSTNode>x = n->left_;
std::shared_ptr<BSTNode>T2 = x->right_;
std::weak_ptr<BSTNode>tempParent = n->parent_;
// Perform rotation
x->right_ = n;
n->left_ = T2;
// Update heights
n->height_ = max(height(n->left_), height(n->right_)) + 1;
x->height_ = max(height(x->left_), height(x->right_)) + 1;
tempParent = x;
// Return new root
return x;
}
std::shared_ptr<BSTNode> AVLTree::leftRotate(std::shared_ptr<BSTNode>n){
std::shared_ptr<BSTNode>y = n->right_;
std::shared_ptr<BSTNode>T2 = y->left_;
std::weak_ptr<BSTNode>tempParent = n->parent_;
// Perform rotation
y->left_ = n;
n->right_ = T2;
// Update heights
n->height_ = max(height(n->left_), height(n->right_)) + 1;
y->height_ = max(height(y->left_), height(y->right_)) + 1;
tempParent = y;
// Return new root
return y;
}
void AVLTree::balance(std::shared_ptr<BSTNode> N) {
if(N != root_){
if(getBalance(N) >= -1 && getBalance(N) <= 1){
if(N != root_){
balance(N->parent_.lock());
}
}
if(getBalance(N) == 2){
if(N->key_ < N->left_->key_){
rightRotate(N);
}
if(N->key_ < N->left_->key_){
N->left_ = leftRotate(N->left_);
rightRotate(N);
}
}
if(getBalance(N) == -2){
if(N->key_ > N->right_->key_){
leftRotate(N);
}
if(N->key_ < N->right_->key_){
N->right_ = rightRotate(N->right_);
leftRotate(N);
}
}
}
N->height_= max( height( N->left_ ), height( N->right_ ) ) + 1;
}
void AVLTree::AVLInsert(int key) {
std::shared_ptr<BSTNode>lastNode;
lastNode = BST::Insert(key);
balance(lastNode);
}
So I'm supposed to implement an AVL tree with an input of a JSON file. So for that reason, I' created an AVLTree class. The problem with this class is that when I use a dataset of, say, 1000, it doesn't work, but it works for a dataset of 10. My AVL rotations don't seem to work either and so the tree is never balanced around the root but otherwise, it works perfectly.
The BST::Insert(key) returns the last node aka the node that was just inserted.
I use smart pointers to point to each value and to move them around in the BST. My BST class uses smart pointers so I would love it if someone could help me out using smart pointers.
Yes, this is an assignment but it's just a small bug I haven't been able to figure out.
BSTNode::BSTNode(int key) :
key_(key),
parent_(std::weak_ptr<BSTNode>()),
left_(nullptr),
right_(nullptr) {}
BSTNode::BSTNode(int key, std::weak_ptr<BSTNode> parent) :
key_(key),
parent_(parent),
left_(nullptr),
right_(nullptr) {}
bool BSTNode::IsLeaf() const {
return left_ == nullptr && right_ == nullptr;
}
bool BSTNode::HasLeftChild() const {
return left_ != nullptr;
}
bool BSTNode::HasRightChild() const {
return right_ != nullptr;
}
void BSTNode::DeleteChild(std::shared_ptr<BSTNode> v) {
if (left_ == v) {
left_ = nullptr;
} else if (right_ == v) {
right_ = nullptr;
} else {
std::cerr << "BSTNode::DeleteChild Error: non-child passed as argument\n";
exit(EXIT_FAILURE);
}
}
void BSTNode::ReplaceChild(std::shared_ptr<BSTNode> v, std::shared_ptr<BSTNode> u) {
if (left_ == u || right_ == u) {
std::cerr << "BSTNode::ReplaceChild Error: child passed as replacement\n";
}
if (left_ == v) {
left_ = u;
u->parent_ = v->parent_;
} else if (right_ == v) {
right_ = u;
u->parent_ = v->parent_;
} else {
std::cerr << "BSTNode::ReplaceChild Error: non-child passed as argument\n";
exit(EXIT_FAILURE);
}
}
int BSTNode::height() {
if (this == nullptr){
return -1;
}
return this->height_;
}
int BSTNode::balanceFactor() {
if (this == nullptr){
return 0;
}
return this->right_->height() - this->left_->height();
}
BST::BST() : root_(nullptr), size_(0) {}
std::shared_ptr<BSTNode> BST::Insert(int key) {
if (root_ == nullptr) {
root_ = std::make_shared<BSTNode>(key);
size_++;
return root_;
}
std::shared_ptr<BSTNode> currentNode = root_, lastNode = nullptr;
while (currentNode != nullptr) {
lastNode = currentNode;
if (key < currentNode->key_) {
currentNode = currentNode->left_;
} else {
currentNode = currentNode->right_;
}
}
if (key < lastNode->key_) {
lastNode->left_ = std::make_shared<BSTNode>(key, lastNode);
} else {
lastNode->right_ = std::make_shared<BSTNode>(key, lastNode);
}
size_++;
return lastNode;
}
bool BST::Delete(int key) {
std::shared_ptr<BSTNode> currentNode = root_;
while (currentNode != nullptr) {
if (currentNode->key_ == key) {
if (currentNode->IsLeaf()) {
DeleteLeaf(currentNode);
} else if (currentNode->left_ == nullptr) {
assert(currentNode->right_ != nullptr);
std::shared_ptr<BSTNode> parent = currentNode->parent_.lock();
parent->ReplaceChild(currentNode, currentNode->right_);
size_--; assert(size_ >= 0);
} else if (currentNode->right_ == nullptr) {
assert(currentNode->left_ != nullptr);
std::shared_ptr<BSTNode> parent = currentNode->parent_.lock();
parent->ReplaceChild(currentNode, currentNode->left_);
size_--; assert(size_ >= 0);
} else {
currentNode->key_ = DeleteMin(currentNode);
}
}
currentNode = (key < currentNode->key_) ?
currentNode->left_ : currentNode->right_;
}
return false;
}
int BST::DeleteMin() {
return DeleteMin(root_);
}
void BST::DeleteLeaf(std::shared_ptr<BSTNode> currentNode) {
std::shared_ptr<BSTNode> parent = currentNode->parent_.lock();
if (parent == nullptr) {
// Delete root
root_ = nullptr;
size_--; assert(size_ == 0);
} else {
if (parent->right_ == currentNode) {
parent->right_ = nullptr;
} else if (parent->left_ == currentNode) {
parent->left_ = nullptr;
} else {
std::cerr << "BST::DeleteLeaf Error: inconsistent state\n";
}
size_--; assert(size_ >= 0);
}
}
int BST::DeleteMin(std::shared_ptr<BSTNode> currentNode) {
std::shared_ptr<BSTNode> lastNode = nullptr;
while (currentNode != nullptr) {
lastNode = currentNode;
currentNode = currentNode->left_;
}
int result = lastNode->key_;
std::shared_ptr<BSTNode> parent = lastNode->parent_.lock();
if (parent == nullptr) {
// lastNode is root
if (lastNode->right_ != nullptr) {
root_ = lastNode->right_;
lastNode->right_->parent_.reset();
} else {
root_ = nullptr;
}
} else {
// lastNode under the root
if (lastNode->right_ != nullptr) {
parent->left_ = lastNode->right_;
lastNode->right_->parent_ = parent;
} else {
parent->left_ = nullptr;
}
}
size_--; assert(size_ >= 0);
return result;
}
size_t BST::size() const {
return size_;
}
bool BST::empty() const {
return size_ == 0;
}
bool BST::Find(int key) const {
std::shared_ptr<BSTNode> currentNode = root_;
while (currentNode != nullptr) {
if (currentNode->key_ == key) {
return true;
}
currentNode = (key < currentNode->key_) ?
currentNode->left_ : currentNode->right_;
}
return false;
}
std::string BST::JSON() const {
nlohmann::json result;
std::queue< std::shared_ptr<BSTNode> > nodes;
if (root_ != nullptr) {
result["root"] = root_->key_;
nodes.push(root_);
while (!nodes.empty()) {
auto v = nodes.front();
nodes.pop();
std::string key = std::to_string(v->key_);
if (v->left_ != nullptr) {
result[key]["left"] = v->left_->key_;
nodes.push(v->left_);
}
if (v->right_ != nullptr) {
result[key]["right"] = v->right_->key_;
nodes.push(v->right_);
}
if (v->parent_.lock() != nullptr) {
result[key]["parent"] = v->parent_.lock()->key_;
} else {
result[key]["root"] = true;
}
result[key]["height"] = v->height();
result[key]["balance factor"] = v->balanceFactor();
}
}
result["height"] = root_->height();
result["size"] = size_;
return result.dump(2) + "\n";
}
And this is the AVLCommands.cxx
#include <string>
#include "json.hpp"
#include <iostream>
#include <fstream>
#include "BST.h"
#include "AVL.h"
int main(int argc, char** argv) {
std::ifstream file1;
file1.open(argv[1]);
nlohmann::json jsonObject;
if (file1.is_open()) {
file1 >> jsonObject;
} else {
std::cout << "Invalid Arguments";
}
AVLTree avl_tree;
int numOps = jsonObject["metadata"]["numOps"];
if(numOps == 10){
for(int i = 0; i < numOps; i++ ){
std::string num;
if(i < 9){
num = "0" + std::to_string(i+1);
}
else{
num = std::to_string(i+1);
}
avl_tree.AVLInsert(jsonObject[num]["key"]);
}
}
if(numOps == 1000){
for(int i = 1; i <= numOps; i++ ){
std::string num;
if(i < 10 && i > 0){
num = "000" + std::to_string(i);
avl_tree.AVLInsert(jsonObject[num]["key"]);
}
if(i < 100 && i >= 10){
num = "00" + std::to_string(i);
avl_tree.AVLInsert(jsonObject[num]["key"]);
}
if(i < 1000 && i >= 100){
num = "0" + std::to_string(i);
avl_tree.AVLInsert(jsonObject[num]["key"]);
}
if(i == 1000){
num = std::to_string(i);
avl_tree.AVLInsert(jsonObject[num]["key"]);
}
}
}
std::cout << avl_tree.JSON() << "\n";
}

AVL-tree node misses content of an included structure and I cannot find why

Consider the following AVL-tree implementation. Each node contains a list of numbers.The key is named workload, but consider it as a plain double variable. If a key is equal to the key of an already existing node, the number gets pushed into the list. Every time I pop a number from a list, I perform a check, if the node's list is empty -> remove the node. But, after the element with key=3 gets removed completely, the list of the node with key=4 is suddenly empty. I've been trying to solve it for over 10 hours now, it's actually the first time I ever needed to ask something here. Pardon me if I miss a few things.
#include<iostream>
#include <list>
using namespace std;
class BST
{
struct node
{
double workload;
list<int> numbers;
node* left;
node* right;
int height;
};
node* root;
unsigned long long size;
bool empty;
void makeEmpty(node* t)
{
if(t == NULL)
return;
makeEmpty(t->left);
makeEmpty(t->right);
delete t;
}
node* insert(double workload,int number, node* t)
{
if(t == NULL)
{
t = new node;
t->workload = workload;
t->numbers.push_back(number);
t->height = 0;
t->left = t->right = NULL;
}
else if(t->workload == workload){
t->numbers.push_back(number);
}
else if(workload < t->workload)
{
t->left = insert(workload, number, t->left);
if(height(t->left) - height(t->right) == 2)
{
if(workload < t->left->workload)
t = singleRightRotate(t);
else
t = doubleRightRotate(t);
}
}
else if(workload > t->workload)
{
t->right = insert(workload, number, t->right);
if(height(t->right) - height(t->left) == 2)
{
if(workload > t->right->workload)
t = singleLeftRotate(t);
else
t = doubleLeftRotate(t);
}
}
//if x == t->workload instead of using int workload. its a list and we push into it.
t->height = max(height(t->left), height(t->right))+1;
return t;
}
node* singleRightRotate(node* &t)
{
node* u = t->left;
t->left = u->right;
u->right = t;
t->height = max(height(t->left), height(t->right))+1;
u->height = max(height(u->left), t->height)+1;
return u;
}
node* singleLeftRotate(node* &t)
{
node* u = t->right;
t->right = u->left;
u->left = t;
t->height = max(height(t->left), height(t->right))+1;
u->height = max(height(t->right), t->height)+1 ;
return u;
}
node* doubleLeftRotate(node* &t)
{
t->right = singleRightRotate(t->right);
return singleLeftRotate(t);
}
node* doubleRightRotate(node* &t)
{
t->left = singleLeftRotate(t->left);
return singleRightRotate(t);
}
node* findMin(node* t)
{
if(t == NULL)
return NULL;
else if(t->left == NULL)
return t;
else
return findMin(t->left);
}
node* findMax(node* t)
{
if(t == NULL)
return NULL;
else if(t->right == NULL)
return t;
else
return findMax(t->right);
}
node* find(node* t,double workload){
if (t->workload == workload){
return t;
}
else if(workload < t->workload && t->left!=NULL)
return find(t->left,workload);
else if(workload > t->workload && t->right!=NULL)
return find(t->right,workload);
else{
cout << "Null node encountered" << endl;
return t;
}
}
node* remove(double x, node* t)
{
node* temp;
// Element not found
if(t == NULL)
return NULL;
// Searching for element
if(x < t->workload)
t->left = remove(x, t->left);
else if(x > t->workload)
t->right = remove(x, t->right);
// Element found
// With 2 children
else if(t->left && t->right)
{
temp = findMin(t->right);
t->workload = temp->workload;
t->right = remove(t->workload, t->right);
}
// With one or zero child
else
{
temp = t;
if(t->left == NULL)
t = t->right;
else if(t->right == NULL)
t = t->left;
delete temp;
}
if(t == NULL)
return t;
t->height = max(height(t->left), height(t->right))+1;
// If node is unbalanced
// If left node is deleted, right case
if(height(t->left) - height(t->right) == -2)
{
// right right case
if(height(t->right->right) - height(t->right->left) == 1)
return singleLeftRotate(t);
// right left case
else
return doubleLeftRotate(t);
}
// If right node is deleted, left case
else if(height(t->right) - height(t->left) == 2)
{
// left left case
if(height(t->left->left) - height(t->left->right) == 1){
return singleRightRotate(t);
}
// left right case
else
return doubleRightRotate(t);
}
return t;
}
int height(node* t)
{
return (t == NULL ? -1 : t->height);
}
int getBalance(node* t)
{
if(t == NULL)
return 0;
else
return height(t->left) - height(t->right);
}
void inorder(node* t)
{
if(t == NULL)
return;
inorder(t->left);
cout << t->workload<< " ";
inorder(t->right);
}
//Reverse inorder (Sorted highest to lowest)
void rinorder(node* t)
{
if(t == NULL)
return;
rinorder(t->right);
cout << t->workload << " ";
rinorder(t->left);
}
void preorder(node* t)
{
if (t == NULL)
return;
cout << t->workload << " ";
preorder(t->left);
preorder(t->right);
}
void postorder(node* t)
{
if (t == NULL)
return;
postorder(t->left);
postorder(t->right);
cout << t->workload << " ";
}
public:
BST()
{
root = NULL;
}
void insert(double workload, int number)
{
root = insert(workload, number, root);
}
void remove(double workload)
{
root = remove(workload, root);
}
void displayrin()
{
cout << "Rinorder: ";
rinorder(root);
cout << endl;
}
void displayin()
{
cout << "Inorder: ";
inorder(root);
cout << endl;
}
void displaypost()
{
cout << "Postorder: ";
postorder(root);
cout << endl;
}
void displaypre()
{
cout << "Preorder: ";
preorder(root);
cout << endl;
}
double getMax(){
return findMax(root)->workload;
}
int getMaxNum(){
return find(root,getMax())->numbers.front();
}
int getNum(double workload){
return find(root,workload)->numbers.front();
}
//We pop a Num from a node
void popnumber(double workload){
node *t = find(root,workload);
if(t!=NULL){
if(!t->numbers.empty()){
t->numbers.pop_front();
//If the Num list of the node is empty, remove node
if(t->numbers.empty()){
remove(t->workload);
}
}
}
}
};
int main()
{
BST t;
//key value pairs
t.insert(2,1);
t.insert(3,1);
t.insert(3,2);
t.insert(4,7);
cout << t.getNum(4) << endl;
cout << t.getNum(3)<<endl;
t.popnumber(3);
cout << t.getNum(3)<<endl;
t.popnumber(3);
t.displayin();
t.displaypost();
t.displaypre();
t.displayrin();
cout << t.getNum(4) << endl;
cout << "The max is : " << t.getMax() << endl;
cout << "The top Num of the Max is : " << t.getMaxNum() << endl;
return 0;
}
As mentioned in the comments, the problem is in the "Element found With 2 children" section of remove.
To remove the element, you find the next element in the tree. Your implementation then wants to copy the contents of the found node (temp). You copy the workload value, so that both t and temp have the same workload value (4). You do not copy the numbers list. The t node has a workload of 4 and an empty numbers list, while temp has a workload of 4 and a numbers list consisting of one element, 7. You then delete temp, losing the list.
One fix would be to copy (or move) numbers from temp to t before removing it from the tree. Adding a MoveData method to node that would move the data fields (while not altering the tree specific fields) would make it easier to add new data fields.
Another fix would be to change how you're doing the data update. If you update all pointers (and other tree related fields like height), then you don't have to worry about the data (and any pointers/iterators to the nodes would not be invalidated).

C++ code working as intended on Linux but not on Windows

I do not know why this code breaks ,probably when adding new node, on Windows .Returns "Process returned -1073741819 (0xC0000005)"),it was compiled with GNU GCC.It works perfectly fine on Linux.
Also tested on geeksforgeeks ide , this is the link https://ide.geeksforgeeks.org/feo8SYMsFP.
When debugged, SIGSEGV is returned when adding node but I am not sure why..
For example, input : 1 10 1 11 then it breaks..
#include <iostream>
#include <stdlib.h>
struct Node
{
int key;
Node * left;
Node * right;
};
class binarySearchTree
{
private:
Node *root;
Node *newNode(int key)
{
Node *temp = new Node;
temp->left = temp->right = NULL;
temp->key = key;
return temp;
}
void traverse_inorder(Node *temp)
{
if (temp==NULL)
return;
traverse_inorder(temp->left);
std::cout <<"Current key: "<< temp->key << "\n";
traverse_inorder(temp->right);
}
void find(Node* temp,int key)
{
if (temp==NULL)
return;
find(temp->left,key);
if (temp->key == key)
std::cout <<"Key " << key << " found\n";
find(temp->right,key);
}
Node* minValueNode(Node* n)
{
Node* x = n;
while (x->left != NULL)
x = x->left;
return x;
}
Node* deleteNode(Node* temp, int key)
{
if (temp == NULL)
return temp;
if (key < temp->key)
temp->left = deleteNode(temp->left, key);
else if (key > temp->key)
temp->right = deleteNode(temp->right, key);
else
{
if (temp->left == NULL)
{
Node *x = temp->right;
delete temp;
return x;
}
else if (root->right == NULL)
{
Node *x = temp->left;
delete temp;
return x;
}
Node* x = minValueNode(temp->right);
temp->key = x->key;
temp->right = deleteNode(temp->right, x->key);
}
return temp;
}
void delete_tree(Node *temp)
{
if (temp == NULL)
return;
delete_tree(temp->left);
delete_tree(temp->right);
delete temp;
}
void traverse_postorder(Node* temp)
{
if (temp == NULL)
return;
traverse_postorder(temp->left);
traverse_postorder(temp->right);
std::cout <<"Current key: "<< temp->key << "\n";
}
void traverse_preorder(Node* temp)
{
if (temp == NULL)
return;
std::cout <<"Current key: "<< temp->key << "\n";
traverse_preorder(temp->left);
traverse_preorder(temp->right);
}
void add(int key)
{
if (root == NULL)
root = newNode(key);
else
{
Node *temp = root;
while (true)
{
if (temp->key > key)
{
if (temp->left == NULL)
{
temp->left = newNode(key);
break;
}
else
temp = temp->left;
}
else if (temp->key < key)
{
if (temp->right == NULL)
{
temp->right =newNode(key);
break;
}
else
temp = temp->right;
}
else
{
std::cout << "Key already added!\n";
break;
}
}
}
}
public:
binarySearchTree()
{
root = NULL;
}
~binarySearchTree()
{
delete_tree(root);
}
void _find(int key)
{
find(root,key);
}
void _del(int key)
{
root = deleteNode(root,key);
}
void _traverse_postorder()
{
traverse_postorder(root);
}
void _traverse_preorder()
{
traverse_preorder(root);
}
void _traverse_inorder()
{
traverse_inorder(root);
}
void _add(int key)
{
add(key);
}
};
int main()
{
binarySearchTree bst;
std::cout << "Binary Search Tree Menu (1-add key, 2-search key, 3-remove key, 4-traverse inorder, 5-traverse postorder, 6-traverse preorder, q-exit)\n";
char input;
do
{
std::cout << "Awaiting input ";
std::cin >> input;
int key;
switch(input)
{
case '1':
std::cout << "Enter key.. ";
std::cin >> key;
bst._add(key);
break;
case '2':
std::cout << "Enter key.. ";
std::cin >> key;
bst._find(key);
break;
case '3':
std::cout << "Enter key.. ";
std::cin>>key;
bst._del(key);
break;
case '4':
bst._traverse_inorder();
break;
case '5':
bst._traverse_postorder();
break;
case '6':
bst._traverse_preorder();
break;
}
}
while (input != 'q');
std::cout << "Deleting Binary Search Tree...\n";
return 0;
}
This code:
struct Node
{
int key;
Node * left;
Node * right;
};
Node *newNode(int key)
{
Node *temp = new Node;
temp->key = key;
return temp;
}
means that newNode returns pointer to node with indeterminate values for left and right. Instead these should be null pointers, (e.g. use new Node(); instead of new Node;).
On the original system it probably happened to get zeroed memory from the allocator so the problem didn't show up.

Self Balancing AVL Tree memory leaks

So I've been working on this self-balancing AVL tree, and I feel like its working correctly, but there are some memory leaks. I've search and gone through a million times it feels like trying to figure out what I'm doing wrong but I'm new to this whole memory leak thing and obviously need to learn more. If anyone can help me out or can see where the leaks may be that would be awesome, here is the code for my AVL tree:
#pragma once
#include <algorithm>
#include <fstream>
#include "LinkedList.h"
template <typename ItemType>
class AVLTreeSet {
private:
struct Node {
ItemType info;
Node* left;
Node* right;
int height;
};
Node* root;
int size;
public:
AVLTreeSet()
{
root = NULL;
size = 0;
}
~AVLTreeSet()
{
clear();
}
void clear()
{
Node* n = root;
if(n != NULL)
{
clearTree(n->left);
clearTree(n->right);
delete n;
}
root = NULL;
}
void clearTree(Node* n)
{
if(n != NULL)
{
clearTree(n->left);
clearTree(n->right);
delete n;
}
}
void print(std::ofstream &out)
{
//cout << "HERE" << endl;
LinkedList<Node*> list;
int level = 0;
int levelSize;
int count = 0;
Node* n = root;
if (n == NULL)
{
return;
}
list.insert(n);
levelSize = list.getSize();
while(list.getSize() != 0)
{
count = 0;
out << "level " << level << ": ";
for (unsigned i = levelSize; i > 0; i--)
{
count++;
if (count > 8)
{
out << std::endl;
out << "level " << level << ": ";
count = 0;
}
n = list.getInfo();
out <<n->info << "(" << getHeight(n) << ") ";
if (n->left != NULL)
{
//cout << "left is not null" << endl;
list.insert(n->left);
}
if (n->right != NULL)
{
list.insert(n->right);
//cout << "right is not null" << endl;
}
list.remove();
}
levelSize = list.getSize();
level++;
out << std::endl;
//levelSize = list.getSize();
}
}
void insert(const ItemType& item)
{
//cout << "Insert FUNCTION" << endl;
Node* current = root;
if (current == NULL)
{
//cout << "ADD FUNCTION NULL" << endl;
current = new Node;
current->info = item;
current->left = NULL;
current->right = NULL;
current->height = 0;
root = current;
size++;
//cout << current->info << endl;
//cout << current->height << endl;
return;
}
if (current->info > item)
{
current->left = add(item, current->left);
}
if (current->info < item)
{
current->right = add(item, current->right);
}
current = balance(current);
root = current;
}
Node* add(const ItemType& item, Node* current)
{
if (current == NULL)
{
current = new Node;
current->info = item;
current->left = NULL;
current->right = NULL;
current->height = 0;
size++;
}
if (current->info > item)
{
current->left = add(item, current->left);
}
if (current->info < item)
{
current->right = add(item, current->right);
}
return current;
}
void remove(const ItemType& item)
{
Node* current = root;
if (current == NULL)
{
//cout << "NULL" << endl;
return;
}
if (current->info == item)
{
//cout << "FOUND" << endl;
current = removeNext(item, current);
current = balance(current);
root = current;
return;
}
if (current->info > item)
{
//cout << "LEFT" << endl;
current->left = removeNext(item, current->left);
if (current == root)
{
root = balance(current);
}
return;
}
if (current->info < item)
{
//cout << "RIGHT" << endl;
current->right = removeNext(item, current->right);
if (current == root)
{
root = balance(current);
}
return;
}
}
Node* removeNext(const ItemType& item, Node* current)
{
Node* temp;
if (current != NULL)
{
if (current->info > item)
{
//cout << "REMOVENEXT LEFT" << endl;
current->left = removeNext(item, current->left);
return current;
}
if (current->info < item)
{
//cout << "REMOVENEXT RIGHT" << endl;
current->right = removeNext(item, current->right);
return current;
}
//cout << "FOUND" << endl;
if (current->left != NULL && current->right != NULL)
{
//cout << "LEFT AND RIGHT CHILDREN" << endl;
temp = current;
current = CTR(current->right);
current->left = temp->left;
//cout << current->info << endl;
//looker = removeNext(current->info, temp->right);
delete temp;
size--;
current = balance(current);
return current;
}
else if (current->right != NULL)
{
//cout << "RIGHT ONE CHILD" << endl;
temp = current;
current = current->right;
delete temp;
size--;
current = balance(current);
return current;
}
else if (current->left != NULL)
{
//cout << "LEFT ONE CHILD" << endl;
temp = current;
current = current->left;
delete temp;
size--;
current = balance(current);
return current;
}
//cout << "CURRENT NODE" << endl;
delete current;
size--;
return NULL;
}
//cout << "NOT FOUND" << endl;
return current;
}
Node* CTR(Node* current)
{
while(current->left != NULL)
{
//cout << "ENTERED LOOP" << endl;
current = current->left;
}
//cout << current->info << endl;
return current;
}
bool find(const ItemType& item)
{
Node* current = root;
bool find = false;
if (current == NULL)
{
return find;
}
if (item == current->info)
{
find = true;
return find;
}
if (current->info > item && current->left != NULL)
{
find = findLeft(item, current->left);
}
if (current->info < item && current->right != NULL)
{
find = findRight(item, current->right);
}
return find;
}
bool findLeft(const ItemType& item, Node* current)
{
bool find = false;
if (item == current->info)
{
find = true;
return find;
}
if (current->info > item && current->left != NULL)
{
find = findLeft(item, current->left);
}
if (current->info < item && current->right != NULL)
{
find = findRight(item, current->right);
}
return find;
}
bool findRight(const ItemType& item, Node* current)
{
bool find = false;
if (item == current->info)
{
find = true;
return find;
}
if (current->info > item && current->left != NULL)
{
find = findLeft(item, current->left);
}
if (current->info < item && current->right != NULL)
{
find = findRight(item, current->right);
}
return find;
}
int getHeight(Node* temp)
{
int h = 0;
if (temp != NULL)
{
int l_height = getHeight(temp->left);
int r_height = getHeight(temp->right);
int max_height = std::max(l_height, r_height);
h = max_height + 1;
}
return h;
}
void setHeight(Node* n)
{
n->height = std::max(getHeight(n->right), getHeight(n->left)) + 1;
}
Node* balance(Node* n)
{
if (size == 1)
{
return n;
}
else if(getHeight(n->left) - getHeight(n->right) > 1) //n is out of balance
{
//cout << "BALANCE RIGHT" << endl;
n = balanceToRight(n);
}
else if(getHeight(n->right) - getHeight(n->left) > 1)
{
//cout << "BALANCE LEFT" << endl;
n = balanceToLeft(n);
}
return n;
}
Node* balanceToRight(Node* n)
{
if(getHeight(n->left->right) > getHeight(n->left->left))
{
n->left = rotateLeft(n->left); //<--- extra step for double rotate
}
n = rotateRight(n); //<--- this is for single
return n;
}
Node* balanceToLeft(Node* n)
{
if(getHeight(n->right->left) > getHeight(n->right->right))
{
n->right = rotateRight(n->right); //<--- extra step for double rotate
}
n = rotateLeft(n); //<--- this is for single
return n;
}
Node* rotateRight(Node* n)
{
Node* temp = n->left;
n->left = temp->right;
temp->right = n;
setHeight(n); //<--- set first
setHeight(temp);
return temp;
}
Node* rotateLeft(Node* n)
{
Node* temp = n->right;
n->right = temp->left;
temp->left = n;
setHeight(n); //<--- set first
setHeight(temp);
return temp;
}
};
I run the program by reading in a file with my main.cpp that calls the commands of my AVLtree. I know its a lot of code but I'm stressing out because I can't find where it maybe happening. Thanks.
How do you know that there are memory leak(s)?
Unless you use some tool to find the memory leak, for example valgrind as suggested by #jsantander, then try the following:
Avoid code duplication. There is too much of duplication in the present form. For example clear() could be simplified by just calling cleartree(root). Similar for insert().
Print/log memory each memory allocation (new) and deallocation (delete)
Keep always increasing counters, newCount and deleteCount. At the end of significant methods, add an assertion, assert( newCount - deleteCount == size );. At the first occurrence of memory leak, the assert() would blow. See http://accu.org/var/uploads/journals/overload102.pdf, page 7, "Other experiences"

Adjacency list to create graph and Breadth First Search (BFS) and Fepth First Search (DFS)

Here is my code which implements graph using adjacency list and do a Breadth First Search (BFS) and Depth First Search (DFS).
While creating graph and adding edges I am facing problem of a fault in creating graph. I am not sure of the pointer that I have used.
Can you suggest where am I wrong?
#include "Graph.h"
#include <iostream>
using namespace std;
int Graph::pop()
{
if (top = -1) {
cout << "empty";
return 0;
} else
return stack[top--];
}
void Graph::push(int value)
{
if (top >= 50) {
cout << "full";
} else
stack[++top] = value;
}
void Graph::add(int val)
{
if (rear != 49)
qu[++rear] = val;
else
cout << "full";
}
int Graph::del()
{
if (rear == front) {
cout << "empty";
return 0;
} else
front += 1;
return qu[front];
}
int Graph::gethead()
{
return rear;
}
int Graph::gettail()
{
return front;
}
node *Graph::createnode(int t)
{
node *temp;
temp = new node;
temp->val = t;
temp->next = NULL;
return temp;
}
Graph::Graph()
{
rear = -1;
front = -1;
top = -1;
}
Graph::Graph(int t)
{
struct arr r[t];
a = r;
for (int i = 0; i < t; i++) {
a[i].key = i;
a[i].begin = NULL;
a[i].end = NULL;
}
int q[t];
p = q;
for (int k = 0; k < t; k++) {
p[k] = 0;
}
}
void Graph::visited(int v1)
{
p[v1] = 1;
}
bool Graph::isvisited(int v1)
{
if (p[v1] == 1)
return true;
else
false;
}
void Graph::addEdge(int v1, int v2)
{
if (a[v1].begin == NULL) {
node *temp = createnode(v2);
a[v1].begin = temp;
a[v1].end = temp;
} else {
node *temp = createnode(v2);
node *temp1 = a[v1].end;
temp1->next = temp;
a[v1].end = temp;
}
if (a[v2].begin == NULL) {
node *temp = createnode(v1);
a[v2].begin = temp;
a[v2].end = temp;
} else {
node *temp = createnode(v1);
//node *temp2=a[v2].end;
//temp2->next=temp;
a[v2].end->next = temp;
//a[v2].end->next=temp;
a[v2].end = temp;
}
}
void Graph::deleteEdge(int v1, int v2)
{
node *temp;
temp = a[v1].begin;
if (a[v1].begin->val == v2) {
a[v1].begin = a[v1].begin->next;
delete(temp);
temp = NULL;
} else {
node *t = temp->next;
while (t != NULL) {
if (t->val == v2) {
temp->next = t->next;
delete(t);
} else {
temp = t;
t = t->next;
}
}
}
node *temp1;
temp1 = a[v2].begin;
if (a[v2].begin->val == v1) {
a[v2].begin = a[v2].begin->next;
delete(temp);
temp = NULL;
} else {
node *t = temp->next;
while (t != NULL) {
if (t->val == v1) {
temp->next = t->next;
delete(t);
} else {
temp = t;
t = t->next;
}
}
}
}
void Graph::BFS(int source)
{
add(source);
visited(source);
node *temp = a[source].begin;
while (temp != a[source].end) {
add(temp->val);
}
int r = del();
cout << r << endl;
while (gethead() != gettail()) {
int v1 = del();
visited(v1);
node *temp1;
temp1 = a[v1].begin;
while (temp1 != NULL) {
if (p[temp1->val] != 1) {
add(temp1->val);
temp1 = temp1->next;
} else
temp1 = temp1->next;
}
if (temp1 == NULL)
cout << v1 << endl;
}
}
void Graph::DFS(int source)
{
int c = source;
cout << c;
visited(c);
node *temp2 = a[source].begin;
while (a[source].end != NULL) {
push(temp2->val);
temp2 = temp2->next;
}
c = pop();
while (top != -1) {
node *temp = a[c].begin;
if (p[c] != 1) {
cout << c;
while (temp != NULL) {
push(temp->val);
temp = temp->next;
visited(c);
c = pop();
}
}
if (p[c] = 1) {
c = pop();
}
}
}
The first obvious mistake is that in line if (top = -1), the = should be replaced with ==.