I get EXC_BAD_ACCESS (code=1, address=0x0) on the 3rd last line where I return a *Bitvector. As you can see in the main I try to flip the 10'th index to 1. I highly suspect the way I manage my memory is the cause, but can't figure out where and how. (Note that the BinTree is not completed, I'm using a mac, and I use vs-code).
struct node {
BitVector b;
node* parent;
node* right;
node* left;
};
class BinTree {
node* root;
node* insert(node* t, int g) {
if (t==NULL) {
t->b.get_bitvector()->at(g) = 1; //Here I try to set the g'th index to be 1 in the bitvector.
}
return t;
}
public:
BinTree() {
root = NULL;
}
void insert(int g) {
root = insert(root, g);
}
};
class BitVector {
vector<short>* bitvector; // construct a pointer
public:
BitVector() {
bitvector = new vector<short>(30); // point the pointer to a vector of size 30.
}
vector<short>* get_bitvector() {
return bitvector; //Exception occurs here
}
};
int main() {
BinTree t;
t.insert(10);
}
EXC_BAD_ACCESS happens when you try to access memory which isn't allocated by the application; which the application has no access privilege to.
I suppose the error is because your not adding nodes to your tree. Your just calling them. And over here: if (t==NULL), t->b.get_bitvector()->at(g) is called only if the node address is 0x0, hence the error.
What you should do is, make the logic to add a node if not found in some way and change t==NULL to t!=NULL.
Note: Try using nullptr and ditch NULL when working with pointers.
Your program is failing at two points.
First, you have to check bintree->t for being NOT null:
if (t != NULL) {
t->b.get_bitvector()->at(g) = 1;
}
Second, you have to initialize your bintree->t with a bitvector instead of a NULL:
public:
BinTree() {
root = new BitVector();
}
Related
Good evening.
I get an access violation exception error when trying to destroy my BST.
There have been posts about this before and I copied their accepted answer's reply and still didn't get the expected result.
So I have this binary search tree implementation. Everything works well, until my code reaches the "return 0" from my int main() function.
I'll leave some code for you.
PQBST::~PQBST()
{
destroy();
}
inline void PQBST::destroy()
{
if (root)
destroy(root);
}
void PQBST::destroy(Node* node)
{
if (node->left) // this is where it gives me and access violation exception 0xDDDDDDDD
destroy(node->left);
if (node->right)
destroy(node->right);
delete node;
}
I know that this kind of error is thrown when you try to delete something that had been already deallocated, but I can't figure out why it would try to destroy my BST twice when I call the destroy function just once in my application (when I'm done with it).
I commented the part where I manually destroy my BST, and after reaching "return 0", it gives me again
Unhandled exception thrown: read access violation.
node was 0xFF12C6AB
so it is not 0xDDDDDDDD but still an error . :|
My nodes look like this:
struct Node
{
Human info;
Node * left;
Node * right;
Node() {};
Node(Human value)
: info(value), left(NULL), right(NULL)
{
}
};
My BST class only has Node* root .
I hope I gave you enough information.
Thank you.
Edit: My nodes look like this now:
struct Node
{
Human info;
Node * left;
Node * right;
Node() { left = NULL, right = NULL; }
Node(Human value): info(value), left(NULL), right(NULL){}
Node(Human value, Node* left, Node* right) : info(value), left(left), right(right) {}
Node& operator=(const Node& n)
{
info = n.info;
left = n.left;
right = n.right;
return *this;
}
Human getInfo() const { return info; }
Node* getLeft() { return left; }
Node* getRight() { return right; }
~Node() { };
};
My PQBST:
class PQBST
{
private:
Node * root;
int m; //spaceship size - given by the user
public:
PQBST() { root = NULL; }
PQBST(int m) : root(NULL), m(m) {}
PQBST(Node* root, int m);
~PQBST();
PQBST::PQBST(Node * root, int m)
{
this->root = root;
this->m = m;
}
If you are going do delete your BST I suggest doing a post order traversal. This would visit the left, right recursively and then the delete the node. This would work provided the tree was constructed correctly.
void PQBST::destroy(Node* node)
{
if (!node) return;
destroy(node->left);
destroy(node->right);
delete node;
}
Having said that, I would suggest moving away from trying to manually manage memory and use std::unique_ptr<T> where T is your node type. I would define them in your BST as std::unique_ptr<Node> left, right;. This avoids the problem altogether.
I know that this kind of error is thrown when you try to delete something that had been already deallocated, but I can't figure out why it would try to destroy my BST twice when I call the destroy function just once in my application (when I'm done with it).
Not sure if I interpret what you said above (in bold) correctly, but aren't you calling PQBST::destroy() already in PQBST::~PQBST()? If you call PQBST::destroy() also manually, would it be called twice when the destructor is called?
While going through runtime, I'm getting a nullptr exception while this code is executing.
bool Tree::Insert(int n)
{
if (root == nullptr) // This is where it throws
{
Node* root = new Node(n);
return true;
}
Initialization in Tree.h
private:
Node* root;
and Tree constructor.
Tree::Tree()
{
root = nullptr;
}
I have coded exactly like this before and it never threw an exception.
UPDATE:
I apologize for the confusion on the extra '}' Tree::Insert(). There's more code in there and they all have a return case. I had this before
Node* newNode = new Node(n);
root = newNode;
but changed it for a different reason.
Node.h
#pragma once
struct Node
{
int data;
Node *left;
Node *right;
// Constructor
Node() { data = 0; left = nullptr; right = nullptr; }
// Parameterized
Node(int d) { data = d; left = nullptr; right = nullptr; }
// Destructor
~Node() { data = 0; }
};
You either access the Tree::Insert member directly (i.e. not via an instance of the Tree class as if it was a static member) or the instance of the Tree class you're using to access the Insert method is not initialized.
In other words, this is null.
nullptr is implementation-specific. when you say,
"I have coded exactly like this before and it never threw an exception."
you may have to check if it was on a different compiler.
I have made a superclass named "tree". I have constructed the tree in this class. Now, I want to pass the root of the constructed tree to another class which is a subclass of tree. But when I try to pass it, the subclass calls the supercalss constructor and sets it to NULL;
struct node
{
struct node *left;
struct node *right;
int val;
};
struct node *create(int val)
{
struct node *temp = (struct node *)malloc(sizeof(struct node));
temp->val = val;
temp->left = temp->right = NULL;
return temp;
};
class tree
{
public:
struct node *root;
tree()
{
root = NULL;
}
void createtree()
{
root = create(5);
}
void preorder()
{
preorderp(root);
}
void preorderp(struct node *p)
{
if(!p) {
return;
}
cout<<p->val<<' ';
preorderp(p->left);
preorderp(p->right);
}
};
This is the definition of my tree class. It just creates a tree with one node having value 5. Now I want to pass the new root created to a subclass of tree.
class treeiterator:public tree
{
struct node *p;
stack<struct node *> s;
public:
treeiterator()
{
p = root;
push(root);
}
bool hasnext();
int next();
private:
void push(struct node *root);
};
I create an object for tree first and then do createtree. Now, when I create an object for treeiterator, it's member p gets sets to NULL since supercalss constructor is also called. How can I just access the tree created in the superclass in subclass?
Full code:
#include <bits/stdc++.h>
using namespace std;
struct node
{
struct node *left;
struct node *right;
int val;
};
struct node *create(int val)
{
struct node *temp = (struct node *)malloc(sizeof(struct node));
temp->val = val;
temp->left = temp->right = NULL;
return temp;
};
class tree
{
public:
struct node *root;
tree()
{
root = NULL;
}
void createtree()
{
root = create(5);
}
void preorder()
{
preorderp(root);
}
void preorderp(struct node *p)
{
if(!p) {
return;
}
cout<<p->val<<' ';
preorderp(p->left);
preorderp(p->right);
}
};
class treeiterator:public tree
{
struct node *p;
stack<struct node *> s;
public:
treeiterator()
{
p = root;
push(root);
}
bool hasnext();
int next();
private:
void push(struct node *root);
};
void treeiterator::push(struct node *t)
{
while(t) {
s.push(t);
t = t->left;
}
}
bool treeiterator::hasnext()
{
return s.empty()?1:0;
}
int treeiterator::next()
{
struct node *t = s.top();
int val = t->val;
s.pop();
if(t->right) {
push(t->right);
}
return val;
}
int main()
{
tree t;
t.createtree();
t.preorder();
treeiterator it;
while(it.hasnext()) {
cout<<it.next()<<' ';
}
}
Because of inheritance every treeiterator is also a tree. This means
treeiterator treeIt;
treeIt.createtree();
will do what OP wants. There is no need to make a separate tree and moving the root around.
However this is a bit odd in the world of C++ because OP is under-using the constructor. For example, node could be:
struct node
{
node *left;
node *right;
int val;
node(int inval):
val(inval),
left(nullptr),
right(nullptr)
// the above is a Member Initializer List. It makes sure all of your
// members are initialized before the body of the constructor runs.
{
}
};
That bit after the : in the constructor is the Member Initializer List.
Now when you allocate a node it's initialized and ready to be linked. For tree
class tree
{
public:
struct node *root; // almost certainly should not be public.
// also should be a std::unique_ptr<node>
tree(int inval)
{
root = new node(5); // note new in place of malloc. new allocates
// storage and calls constructors. malloc should
// only be used in C++ in rare edge-cases.
}
/* obsolete
void createtree()
{
root = create(5);
}
*/
...
};
tree is assigned a root on allocation. treeiterator is a wee bit trickier because it must call tree's constructor to set up root.
class treeiterator:public tree
{
struct node *p; // Don't see the point off this
stack<struct node *> s; // or this, but that's another question
public:
treeiterator(int inval):
tree(inval) // call's tree's constructor
{
}
bool hasnext();
int next();
private:
void push(struct node *root);
};
Allocating a treeiterator now guarantees that it is all ready to go with no further work.
treeiterator treeIt(5); // all done.
All of the above is covered within the first few chapters of any good C++ programming text. I recommend getting one and reading it, because right now it looks like you are trying to write bad C.
Off topic 1:
You are going to quickly find that this code is in violation of the Rule Of Three. What is The Rule of Three? If you don't know, read the link. It will save you much time and hair-pulling
Off Topic 2:
#include <bits/stdc++.h>
using namespace std;
Is a ticking time bomb. The first line includes the entire standard library, but only in GCC. Your code is now doing far, far more work than it need to to compile, is no longer standard C++, and is not portable to other compilers and may well break with the next revision of GCC. Don't use anything in bits. It internal compiler-specific stuff with no guarantees what-so-ever.
More here: Why should I not #include <bits/stdc++.h>?
The second line takes everything in the std namespace and places it in the global namespace. This leads to fun games like is reverse or std::reverse being called? Often this leads to insane and arcane compiler messages because the poor compiler is confused as hell, but sometimes it's not confused and picks the best choice among the many and silently breaks something else. Great fun debugging.
More here: Why is "using namespace std" considered bad practice?
Together you have the entire standard library pulled into your file AND stripped of it's proper namespace. This results in a vast minefield of potential hidden pain that is not worth any perceived time savings. One of the resulting bugs could cost more clean up than years of typing a few extra lines per file and characters.
No one want to clean up code with this stupid a mistake, so doing this in a professional setting can be costly.
First, you should not have root has public. This is a gross OO error. If you want it to be available to subclasses you should make it protected.
I have a problem with working with c++ pointers. I'm trying to code a splay tree by using a Node struct and Tree struct. However, upon testing, I have encountered a problem. The portion of my code that's not working is below:
struct Node {
Node* l, *r, *p;
int v;
Node() {}
Node(int _v, Node* _p) : v(_v), p(_p) {}
};
struct Tree {
Node* root;
Tree() : root(0) {}
//...
void insert(int k) {
if (!root) {
root = new Node(k, 0);
return;
}
Node* cur = new Node();
cur->v = root->v;
while (1) {
int x = cur->v;
cout << x << endl;
return;
if (k <= x) {
//cout << x << endl;
//return;
if (!cur->l) {
cur->l = new Node(k, cur);
//splay(cur->l);
return;
} else cur = cur->l;
} else {
if (!cur->r) {
cur->r = new Node(k, cur);
//splay(cur->r);
return;
} else cur = cur->r;
}
}
}
//...
};
int main() {
Tree t = Tree();
t.insert(1);
t.insert(5);
return 0;
}
First, I inserted a node with value 1 in the tree; since there was no root, the tree assigned its root as a new node with value 1. Then, when I inserted 5 into the tree, something weird happened. If you leave the code like it is (keeping the first cout), then it will print out 1 for x. However, if you comment out the first cout and return and uncomment the second cout and return, you'll find that it prints out a random garbage number for x, even though no modifications were made. Can somebody tell me what's wrong?
C++ does not initialize class members automatically.
struct Node {
Node* l, *r, *p;
int v;
Node() {}
Node(int _v, Node* _p) : v(_v), p(_p) {}
};
When you create a new node in your code C++ allocates a piece of memory for the Node but it will not clear it. So the values of l, r & p will be whatever was there.
In your algorithm the tests: if (!cur->r) & (!cur->l) currently fail because there is uninitialized garbage in the nodes and not NULL.
As a result when you try to insert the second node the algorithm thinks that there is a valid node to the right of root. And tries to read the memory there and the value there which is the junk x you see. Depending on the value of the junk it may also crash for some people running the code :)
Also I'm 99.9% certain that Node* cur should be a pointer to a Node in the tree and not a new node so:
Node* cur = new Node(); cur->v = root->v; is wrong and should be Node* cur = root;
Proper Initialization -
In c++11 you can do:
struct Node {
Node* l = nullptr;
Node *r = nullptr;
Node *p = nullptr;
int v = 0;
Node() {}
Node(int _v, Node* _p) : v(_v), p(_p) {}
};
Otherwise
struct Node {
Node* l;
Node *r;
Node *p;
int v;
Node() : l(NULL), r(NULL), p(NULL), v(0){}
Node(int _v, Node* _p) : l(NULL), r(NULL), p(_p), v(_v) {}
};
You should initialize members of a class in the same order they were defined.
Now there are a lot of other things that are problematic in the code:
Tree seems to allocate lots of nodes but does not release any memory. (easiest to just use unique_ptr for l and r and root Node)
Is tree the owner of subnodes? Or should it be Node owning and allocating left and right? (goes away if you use std::unique_ptr for left and right)
You are not initializing the members in the order they are defined. This can cause all kind of errors. (since the compiler reorders initialization without telling you)
Node and Tree handle raw pointers but do not define a proper operator=, copy ctor (or delete them) (goes away if you use unique_ptr)
Tree is missing a dtor to clean allocated memory (goes away if you use unique_ptr)
I am trying to implement a custom tree structure, but I am getting a weird output.
enum letter{B,A,T,G,C,N};
struct Node {
int ltr;
Node* ptr;
};
class GTree
{
public:
GTree(int);
void insert(int);
private:
Node* root;
void insert(int l,Node* leaf);
};
GTree::GTree(int l)
{
root->ltr=l;
}
void GTree::insert(int l, Node *leaf)
{
cout<<leaf->ltr;
}
void GTree::insert(int l)
{
if(root==NULL)
{
insert(l, root);
}
else
{
root= new Node;
insert(l,root);
}
}
int main()
{
GTree tree=GTree(T);
tree.insert(T);
}
The output comes out as -2062064467 even though I was expecting 2. Whats going on here? I was looking at a simple BTree implementation, but intending to repurpose it for my desired data structure.
You didn't create a Node object when you first created the GTree object.
GTree::GTree(int l)
{
root->ltr=l;
}
should be
GTree::GTree(int l)
{
root = new Node();
root->ltr=l;
}
Also, make sure you have a destuctor to clean up the resources.
Something else I feel I should point out is that GTree::insert(int l, Node *leaf) perhaps doesn't do what you expect it to do.
cout<<leaf->ltr;
The code above only outputs the integer value in the node but not actually assigning it.
But perhaps you haven't completed that part yet. :-)
You hadn't initialized root, so root->ltr=l; produces undefined behavior. Add root = new Node(); first.
I ran your code and got the output 0 on Ubuntu 12.04 with gcc 4.6.3.