Yes I am still learning C++ and I am trying to create my own Hash.h header with several hash functions (non-cryptic) such as MurmurHash and CityHash. To start this off I just wanted a very basic implementation first. But it is not compiling as I have some memory errors. It is due to adding a entry where data is passed to the class function. Changing to pointers/references gave similar errors and I just can't seem to fix it. Can somebody see what is going wrong such that I know what to look for in the future? Thanks!
//Hash.h
template<class T>
class HashEntry{
private:
int key;
T data;
public:
HashEntry() {};
void putData(T input, int keyVal){
//SEGMENTATION FAULT HAPPENS HERE!!
key = keyVal;
data = input;
}
T getData(){
return data;
}
};
template<class T>
class Hash{
private:
int myFunc;
size_t sizeHash;
HashEntry<T> **table;
public:
Hash(int func, size_t size): myFunc(func), sizeHash(size-1) {
table = new HashEntry<T>*[sizeHash];
for (int i=0;i<sizeHash;i++) table[i] = NULL;
}
int hashFunc(int key){
try{
if (myFunc == 0){
return key % sizeHash;
} else if (myFunc == 1){
//other has func's
} else {string excep = "No such hash function!"; throw excep;}
} catch(string e) {cout << "Hash::hashFunc(): Exception Raised: " << e << endl; exit(0);}
return -1;
}
void addEntry(T data, int key){
int myHash = hashFunc(key);
table[myHash]->putData(data, key);
}
};
Call from main:
Hash<char> *myHash = new Hash<char>(0,10);
myHash->addEntry('s', 11);
return 0;
Related
Using addElemento() from the template class below gives me a segfault immediatly after its execution, and I can't understand why.
template <typename tipoT>
class Celula{
private:
tipoT elem;
Celula *prox;
public:
Celula() { prox = nullptr; }
friend class LinkedList<tipoT>;
};
template <typename tipoT>
class LinkedList{
private:
int tamanho;
Celula<tipoT> *cabeca;
Celula<tipoT> *ultima;
public:
LinkedList() : tamanho(0) { cabeca = new Celula<tipoT>(); ultima = cabeca; }
~LinkedList() { limpaLista(); delete cabeca; }
int getTamanho() { return tamanho; }
bool estaVazia() { return tamanho == 0; }
tipoT *getElemento(int);
void addElemento(tipoT);
void limpaLista();
};
template <typename tipoT>
void LinkedList<tipoT>::addElemento(tipoT novoElem){
Celula<tipoT> *nova = new Celula<tipoT>();
nova->elem = novoElem;
ultima->prox = nova;
ultima = nova;
tamanho++;
}
template <typename tipoT>
tipoT *LinkedList<tipoT>::getElemento(int id){
erroAssert(id > 0, "ID smaller or equal to zero");
erroAssert(id <= tamanho, "ID bigger than size");
Celula<tipoT> *aux = cabeca;
for(int i = 0; i < id; ++i){
erroAssert(aux != nullptr, "Null cell");
aux = aux->prox;
}
return &aux->elem;
}
My test main:
int main(){
LinkedList<int> *listaDeInts = new LinkedList<int>();
cout << "Lista criada." << endl;
listaDeInts->addElemento(20);
cout << *listaDeInts->getElemento(1) << endl;
return 0;
}
that when executed, prints in the console:
Lista criada.
Segmentation fault
Celula has no destructor, and getElemento() returns the item's address correctly. So why does the segfault happen? While debugging in gdb the execution stops as addElemento() ends, so I don't understand what's happening.
So, as part of my assignment in Computer Science, which was to read tweets and put them into a custom Dictionary, I had to, you guessed it, create a dictionary. However, during testing with the dictionary, I encountered an error which I have been unable to fix, despite hours of attempted troubleshooting. I have narrowed it down, and determined that the error lies on line 144, somewhere in the statement cout<<j.get("name").getFront()->getText();, but I have been unable to determine which part of this causes issues, even when breaking it down by parts, except that it begins when I add in the ->getText(), however I heavily suspect that the problem starts earlier on.
I am sorry if I am not too specific, or if I ramble too much, I have just been having trouble with this for a while, and am beginning to get frustrated.
I understand not all the execution or style is the best, so I may ask you to refrain from leaving comments on the way things are done, unless it may directly relate to the problem at hand.
Thank you for any and all help.
/*********************************************************************************************************************
* [REDACTED] *
* CS 101-- Project 4 (Hashing Twitter) *
* This program stores Twitter posts in a hash table * *
*********************************************************************************************************************/
#include <iostream>
#include <stdlib.h>
#include <vector>
using namespace std;
class tweet {
private:
string create_at;
string text;
string screen_name;
public:
string getCreate_at() {
return create_at;
};
string getText() {
return text;
};
string getScreen_name() {
return screen_name;
};
void setCreate_at(string c) {
create_at=c;
};
void setText(string c) {
text=c;
};
void setScreen_name(string c) {
screen_name=c;
};
};
class LinkedList {
public:
tweet* getFront() {
return top;
};
LinkedList* getNext() {
return next;
};
void setNext(LinkedList* c) {
next = c;
};
void setTweet(tweet c) {
top = &c;
};
void setTweet(tweet* c) {
top = c;
};
void insertFront(tweet c) {
LinkedList temp;
temp.setTweet(top);
temp.setNext(next);
this->setTweet(c);
this->setNext(&temp);
};
tweet* removeFront() {
tweet* temp;
temp = top;
if(next != NULL){
top = next->getFront();
if(next->getNext() != NULL)
next = next->getNext();
}
return temp;
};
private:
tweet* top;
LinkedList* next;
};
class HashTable {
private:
vector<LinkedList> store [256];//access by firstcharacter of name as index of array then search through vector linearly until find key
LinkedList getLinkedList(string c) {
vector<LinkedList> temp=store[(int)c.c_str()[0]];
for(int i =0;i<temp.size();i++) {
if(temp.at(i).getFront()->getScreen_name()==c) {
return temp.at(i); //gets list of tweets
}
};
};
bool keyExists(string c) {
vector<LinkedList> temp = store[(int)c.c_str()[0]];
for(int i =0;i<temp.size();i++) {
if(temp.at(i).getFront()->getScreen_name()==c) {
return true; //gets list of tweets
}
};
return false;
};
void insertTweet(tweet c){
if(keyExists(c.getScreen_name())){
getLinkedList(c.getScreen_name()).insertFront(c);
} else {
LinkedList temp;
temp.setTweet(c);
store[c.getScreen_name().c_str()[0]].push_back(temp);
}
};
public:
void put(tweet c) {
insertTweet(c);
};
LinkedList get(string key) {
return getLinkedList(key);
};
bool contains(string key) {
return keyExists(key);
};
void remove(string key) {
vector<LinkedList> temp=store[key.c_str()[0]];
for(int i =0;i<temp.size();i++) {
if(temp.at(i).getFront()->getScreen_name()==key) {
temp.erase(temp.begin()+i); //gets list of tweets
}
};
};
};
HashTable parser(string filename) {
//backslashes
};
int main(int argc, char *argv[])
{
tweet hello;
hello.setText("hello");
hello.setScreen_name("user");
hello.setCreate_at("10211997");
tweet heyo;
heyo.setText("heyo");
heyo.setScreen_name("name");
heyo.setCreate_at("79912101");
LinkedList jerome;
jerome.insertFront(hello);
cout<<jerome.getFront()->getText()<<endl;
jerome.insertFront(heyo);
cout<<jerome.removeFront()->getText()<<endl;
HashTable j;
j.put(heyo);
cout<<j.get("name").getFront()->getText();
}
You are getting the addresses of temporaries:
void insertFront(tweet c) {
LinkedList temp;
temp.setTweet(top);
temp.setNext(next);
this->setTweet(c); //should be &c, but c is a temporary!
this->setNext(&temp); //temp is a temporary!
};
Also, in HashTable, you need put and insertTweet to have a tweet& parameter.
Finally, still in insertTweet, you should pass the address of c to setTweet.
Note that this code is very fragile, as you will have dangling pointers as soon as the tweet objects go out of scope.
I'm looking for an efficient way to check if a POD variable is altered between two cycles. I've come up with this solution:
class Foo {
public:
template<typename T>
bool isChanged(T& entry);
void endCycle();
private:
std::map<void*,size_t> entryMap; // <Address orig.,Size>
std::map<void*,void*>oldVals; // <Address orig., Address cpy.>
};
template<typename T> bool Foo::isChanged(T& entry)
{
entryMap[&entry] = sizeof(T);
if(oldVals[&entry] == NULL)
return false;
if(memcmp(&entry, oldVals[&entry], entryMap[&entry]))
return true;
else
return false;
}
void Foo::endCycle()
{
// Copy all the bytes to save them for the next cycle
for( std::map<void*,size_t>::iterator entryIt = entryMap.begin();
entryIt != entryMap.end();
++entryIt)
{
if(oldVals[entryIt->first] == NULL)
oldVals[entryIt->first] = malloc(entryIt->second);
memcpy(oldVals[entryIt->first], entryIt->first, entryIt->second);
}
}
Now i can use it like this:
Foo gBar;
void aFunction()
{
int ar;
char ba[3][3];
// Some code where ar and ba are filled
if(gBar.isChanged(ar))
// Do Something
if(gBar.isChanged(ba))
// Do Something
gBar.endCycle();
}
Is this an efficient way? My goal was a method which is very easy to use inside various cyclically called functions. I cleaned all the init and free logic from the code. Any suggestions? I especially don't like the oldshool malloc, memcpy and memcmp stuff but i don't know any other way how to do it.
Edit: Found a good solution based on Red Alerts suggestions.
I think you can use templates a little more effectively here.
template <typename T>
class Foo
{
public:
static std::map<T*, T> values;
static bool isChanged(T& entry)
{
auto it = values.find(&entry);
if(it == values.end())
{
values[&entry] = entry;
}
else if(entry != it->second)
{
it->second = entry;
return true;
}
return false;
}
};
template <typename T>
std::map<T*, T> Foo<T>::values;
int main() {
int ar = 3;
cout << Foo<int>::isChanged(ar) << endl; // 0
ar = 4;
cout << Foo<int>::isChanged(ar) << endl; // 1
for(auto& value : Foo<int>::values)
cout << value.second << endl; // 4
return 0;
}
This way you get one map per type, and you don't have to worry about inadvertently messing up an alias. You do need to define operator != and have a working copy constructor for your types, but that is much better than blindly using memcmp and memcpy.
You can also make further template specializations for arrays if you need to compare those (will be a bit more code, but nothing very complicated)
Edit: To get you started, this is what your template signature should look like:
template<class T, size_t N> bool isChanged(T(&entry)[N]); //will be called for stack allocated arrays
Or you can use char* to alias all of your values. This will let you use a single map for everything (like you were doing before, but this has no memcpy/memcmp). It will only work for POD. We could manually call the destructor when overwriting the buffer, but since there is no good way to do this in the class's destructor, it's probably best to leave out heap allocated data altogether.
class Foo
{
std::map<char**, char*> values;
public:
~Foo()
{
for(auto& value : values)
{
delete[] value.second;
}
}
template<typename T> bool isChanged(T& entry)
{
char** addr = reinterpret_cast<char**>(&entry);
auto it = values.find(addr);
if(it == values.end())
{
alignas(T) char* oldBuf = new char[sizeof(T)];
T* oldEntry = new(oldBuf) T;
*oldEntry = entry;
values[addr] = oldBuf;
}
else if(entry != *(reinterpret_cast<T*>(it->second)))
{
T* oldEntry = new(it->second) T;
*oldEntry = entry;
return true;
}
return false;
}
};
After many hours i think i found a good solution. The call stays easy and there are no casts. It's a lot more complex than the C-Style version with memcopy but I think its nicer and has also the benefit that it works with complex data not just POD.
class Manager
{
public:
~Manager()
{
funcPtrs.clear();
}
void adFnc(void(*function)())
{
funcPtrs.push_back(function);
}
void runAll()
{
for(auto& val : funcPtrs)
val();
}
private:
std::vector<void (*)()> funcPtrs;
};
Manager gAllClearManager;
template<typename T>
class Data
{
public:
Data()
{
gAllClearManager.adFnc(clearValues);
}
static void clearValues()
{
values.clear();
}
static std::map<T*,std::vector<T>>& getValues() { return values; }
private:
static std::map<T*,std::vector<T>> values;
};
template <typename T>
static bool isChanged(T& entry)
{
const static Data<T>* dataP = new Data<T>();
static std::map<T*,std::vector<T>>& values = dataP->getValues();
auto it = values.find(&entry);
if(it == values.end())
{
values[&entry].push_back(entry);
}
else if(entry != it->second[0])
{
it->second[0] = entry;
return true;
}
return false;
}
template<typename T, size_t N>
bool isChanged(T (&entry)[N])
{
const static Data<T>* dataP = new Data<T>();
static std::map<T*,std::vector<T>>& values = dataP->getValues();
auto it = values.find(entry);
if( it == values.end())
{
for(int i = 0; i < N ; ++i )
values[entry].push_back(entry[i]);
return false;
}
else
{
for(int i = 0; i < N ; ++i )
{
if(it->second[i] != entry[i])
{
for(int j = 0; j < N ; ++j )
{
it->second[j] = entry[j];
}
return true;
}
}
}
return false;
}
template<typename T>
std::map<T*, std::vector<T>> Data<T>::values;
Now i can use it like:
int main() {
int ar;
std::string ba[6];
if(isChange(ar))
// Do something
if(isChange(ba))
// Do something
}
My first template is finally working! :) Thanks again Red Alert.
I declared the size of the array to be 2 and I tried inserting on the 3rd array position. The insert function is supposed to throw -1 when the position > size+1(using pos-1 when assigning the element into the array) but the throw is not stopping the assignment for the 3rd array position so I am getting a segmentation fault.
template <class T, int N>
class person : public people<T>
{
private:
T a[N];
int size;
public:
person();
virtual void insert(int pos, T info);
virtual T show(int pos);
};
template<class T, int N>
person<T,N>::person(){
size = 0;
}
template <class T, int N>
void person<T,N>::insert(int pos, T info){
if (pos <= 0 || pos > size+1)
throw -1;
a[pos-1] = info;
++size;
}
template <class T, int N>
T person<T,N>::show(int pos){
if ( pos <= 0 || pos > size+1 )
throw -1;
return a[pos-1];
}
void putin( people<name>*& aPerson ) {//passing aPerson itself
string first("Julia"), last("Robert");
name temp(first, last);
string ft("Delilah"), lt("McLuvin");
name temp2(ft, lt);
string fst("oooh lala"), lst("broomdat");
name temp3(fst, lst);
try{
aPerson-> insert(1,temp);
aPerson-> insert(2,temp2);
aPerson-> insert(3,temp3);
}
catch(...){ cout<< "error\n";}
}
int main(){
people<name>* aPerson = new person<name, 2>();
putin(aPerson);
try{
cout << aPerson->show(1);
cout << aPerson->show(2);
cout << aPerson->show(3);
}
catch(...){ cout<< "error\n";}
return 0;
}
Every time you insert something, you check size variable and later increment it. When you hit size == N, nothing happens. You just step out of array bounds, you need to consider case when size is about to get bigger than your array.
Are you using STL? If yes better try using vector<T>::at secure method which will do all necessary checks for you and throw std::out_of_range exception when getting outside its bounds.
There are many questions like this but after looking at some cases, I guess this question is case-specific so I post my code and pointed out where the problem takes place may you be patient reading my code?
uniBTree.h
#ifndef uniBTree_H
#define uniBTree_H
#include "uniTreeNode.h"
#include <cassert>
template<class T>
class uniBTree {
private:
uniTreeNode<T> *root;
int delete_helper(uniTreeNode<T> *);
uniTreeNode<T> *insert_helper(uniTreeNode<T> *, const T);
void in_print_helper(const uniTreeNode<T> *) const;
void pre_print_helper(const uniTreeNode<T> *) const;
void post_print_helper(const uniTreeNode<T> *) const;
public:
uniBTree(void);
uniBTree(uniTreeNode<T> *r);
~uniBTree(void);
void insert(const T i);
void in_print(void) const;
void pre_print(void) const;
void post_print(void) const;
};
template<class T>
uniBTree<T>::uniBTree(void)
{
root = NULL;
}
template<class T>
uniBTree<T>::uniBTree(uniTreeNode<T> *r)
{
root = r;
}
template<class T>
int uniBTree<T>::delete_helper(uniTreeNode<T> *n)
{
int count = 0;
if (n == NULL)
return 0;
count += delete_helper(n->get_left());
count += delete_helper(n->get_right());
delete n;
count++;
return count;
}
template<class T>
uniBTree<T>::~uniBTree(void)
{
int count = delete_helper(root);
std::cout << "uniBTree<T>::~uniBTree<T>(void)\n";
std::cout << count << " nodes deleted\n";
}
template<class T>
void uniBTree<T>::in_print() const
{
in_print_helper(root);
}
template<class T>
void uniBTree<T>::pre_print() const
{
pre_print_helper(root);
}
template<class T>
void uniBTree<T>::post_print() const
{
post_print_helper(root);
}
template<class T>
void uniBTree<T>::in_print_helper(const uniTreeNode<T> *current) const
{
if (current == NULL)
return;
in_print_helper(current->get_left());
current->print();
in_print_helper(current->get_right());
}
template<class T>
void uniBTree<T>::pre_print_helper(const uniTreeNode<T> *current) const
{
if (current == NULL)
return;
current->print();
pre_print_helper(current->get_left());
pre_print_helper(current->get_right());
}
template<class T>
void uniBTree<T>::post_print_helper(const uniTreeNode<T> *current) const
{
if (current == NULL)
return;
post_print_helper(current->get_left());
post_print_helper(current->get_right());
current->print();
}
template<class T>
void uniBTree<T>::insert(const T i)
{
if (root == NULL)
root = new uniTreeNode<T>(i, NULL, NULL);
else
insert_helper(root, i);
}
template<class T>
uniTreeNode<T> *uniBTree<T>::insert_helper(uniTreeNode<T> *current, const T i)
{
if (current == NULL) {//this is will only dealed by attempting to visit leaves...
//if root is null, it'll be handled in insert
uniTreeNode<T> *child = new uniTreeNode<T>(i, NULL, NULL);
assert(child != NULL);
return(child);
}
if (i < current->get_data())
current->set_left(insert_helper(current->get_left(), i));
else
current->set_right(insert_helper(current->get_right(), i));
return(current);
}
#endif
uniTreeNode.h
#ifndef uniTreeNode_H//for redefinition
#define uniTreeNode_H
#include <iostream>
//using namespace std; don't use using namespace xxx and include source file in .h file
template<typename T>
class uniTreeNode {
private:
T data;
uniTreeNode<T> *left;
uniTreeNode<T> *right;
public:
//uniTreeNode<T>(void);
uniTreeNode(T d, uniTreeNode<T> *l, uniTreeNode<T> *r);
T get_data(void) const;
uniTreeNode<T> *get_left(void) const;
uniTreeNode<T> *get_right(void) const;
void set_left(uniTreeNode<T> *l);
void set_right(uniTreeNode<T> *r);
void print() const;
};
template<typename T>
uniTreeNode<T>::uniTreeNode/*remember syntax here*/
(T d , uniTreeNode<T> *l = NULL, uniTreeNode<T> *r = NULL)
{
data = d;
left = l;
right = r;
}
template<typename T>
T uniTreeNode<T>::get_data(void) const
{
return data;
}
template<typename T>
uniTreeNode<T> * uniTreeNode<T>::get_left(void) const
{
return left;
}
template<typename T>
uniTreeNode<T> * uniTreeNode<T>::get_right(void) const
{
return right;
}
template<typename T>
void uniTreeNode<T>::set_left(uniTreeNode<T> *l)
{
left = l;
}
template<typename T>
void uniTreeNode<T>::set_right(uniTreeNode<T> *r)
{
right = r;
}
template<typename T>
void uniTreeNode<T>::print() const
{
std::cout << "data is " << data << std::endl;
}
#endif
date.h
#include <ostream>
class date{
private:
int y;
int m;
int d;
public:
date();//default constructor
date(const long int);//used by cplr as convert constructor
date(int, int , int);
friend bool operator<(const date &d1, const date &d2);//d1 is for left-hand date
friend bool operator>(const date &d1, const date &d2);
bool operator==(date d);
bool operator!=(date d);
date &operator=(date d);
friend std::ostream &operator<<(std::ostream &out, date d);
friend std::istream &operator>>(std::istream &in, date d);
};
date.cc
#include <iostream>
#include <cstdio>
#include <time.h>
#include <cstring>
#include "date.h"
date::date(){
y = m = d = 0;
}
date::date(int Y, int M, int D){
y = Y;
m = M;
d = D;
}
date::date(const long int s){//#second since 1970/1/1 00:00:00
struct tm *buf;
buf = gmtime(&s);
y = (buf->tm_year+1900);
m = buf->tm_mon+1;
d = buf->tm_mday;
}
bool operator<(const date &d1, const date &d2){
bool result;//sizeof(bool) is 1
if(d1.y < d2.y) result = true;
else if(d1.y == d2.y){
if(d1.m < d2.m) result = true;
else if(d1.m == d2.m){
if(d1.d < d2.d) result = true;
else result = false;
}
else result = false;
}
else result = false;
return result;
}
bool operator>(const date &d1, const date &d2){
bool result;//sizeof(bool) is 1
if(d1.y > d2.y) result = true;
else if(d1.y == d2.y){
if(d1.m > d2.m) result = true;
else if(d1.m == d2.m){
if(d1.d > d2.d) result = true;
else result = false;
}
else result = false;
}
else result = false;
return result;
}
bool date::operator==(date d){
return (this->y==d.y && this->m==d.m && this->d==d.d);
}
bool date::operator!=(date d){
return (this->y!=d.y || this->m!=d.m || this->d!=d.d);
}
date &date::operator=(date d){
this->y = d.y;
this->m = d.m;
this->d = d.d;
return *this;
}
std::ostream &operator<<(std::ostream &out, date d){
out << d.y << "/" << d.m << "/" << d.d << std::endl;
return out;
}
std::istream &operator>>(std::istream &in, date d){
in >> d.y >> d.m >> d.d ;
return in;
}
main function
#include "uniBTree.h"
#include "date.h"
#include <cstdio>
int main(){
date d1 = 100000000;//convert constructor
uniTreeNode<date> node(d1, NULL, NULL);
printf("%p %p\n", node.get_left(), node.get_right());
std::cout << node.get_data() << std::endl;
date d2 = 86401;
date d3 = 200000000;
uniBTree<date> btree(&node);
return 0;
}
I tested and found that its &node that is invalid. I think it is because it tries to "release" btree at the end of the program and when the root is encountered, because it points to node, it can't perform good thing.
I have two question:
if construct a node like what I did,(uniTreeNode<date> node(xxx, xxx, xxx);) was the object "NEW"ed by the program?
for the uniTreeNode<T> class template, I didn't write its destructor!! So, like what I say above, when node,which is pointed by root of btree, is to be released is there so-called "default destructor"? and is it called here ? And most importantly, is "DELETE" used by the program?
If one of the two question above is no, is it why the problem arise?
EDIT: now the problem is shown, but how can I adjust my code to fix this? any one any idea?
EDIT: just modify like this:
uniTreeNode<date> *nodeptr = new uniTreeNode<date>(d1, NULL, NULL);
p.s. if not indirectly using a pointer to refer to our root of the btree(thus using new), new isn't used, and delete shouldn't be used; by this choice, delete_helper of uniTreenode should use this:
if(n != root){
delete n;
count++;
}
but this does not solve the problem...
the ultimate question is:
"can we release object without using delete(because it isn't obtained from newing) in c++?"
REPLY:
My "release"/"allocated" is actually saying about the memory, without specifying HOW it is done...but it's a big issue anyway
You say "you can do that but it is almost always the wrong answer";you mean that I should use DELETE but not directly call the destructor?(actually that doesn't seem proper at all)
-->please justify here
Btw, for those instance NEWed by me, is it necessary for them to be DELETED by a statement if I want to release them? or they'll also be dealt like those automatic variable instance?(back when out of scope, by compiler)
-->please correct the above if needed
another Q: isn't there ANY existing statement I can use to do things, like what DELETE does, for those automatic instance? or, I can only call destructor, if I wish?
Answer to your questions:
No, it allocated memory on the stack at compilation time and just ran the constructor on that.
You can't delete a pointer not allocated using new. The compiler inserts a call to the destructor (default or not) for uniTreeNode when the object node is done in main().
So to surmise, you cannot use delete on a pointer that is not allocated using new.
Simplest fix would be to allocate node using new:
uniTreeNode<date>* node = new uniTreeNode<date>(d1);
uniBTree<date> btree(node);
Learn to use valgrind.
It tells you right away what the problem is, you're deleting a stack object in the uniBTree destructor
==23648== Invalid free() / delete / delete[] / realloc()
==23648== at 0x4A0736C: operator delete(void*) (vg_replace_malloc.c:480)
==23648== by 0x400D78: uniBTree<date>::delete_helper(uniTreeNode<date>*) (uniBTree.h:48)
==23648== by 0x400CD5: uniBTree<date>::~uniBTree() (uniBTree.h:56)
==23648== by 0x400B91: main (main.cc:17)
==23648== Address 0x7fefffab0 is on thread 1's stack
==23648==
The destructor calls delete but &node was not created by new (you can tell that because you didn't write new!)