Kareem Aboughazala Kareem Aboughazala - 21 days ago 5
C++ Question

Copy constructor and assignemnt operator overload not working in C++

I am implementing a HashMap class with a destructor, copy constructor and assignment operator. When the I create a HashMap object and add a key and value to it and try assigning it to a new empty object I get a "double free or corruption" error. However if I do the same without adding any keys to the HashMap the code runs fine. I also noticed that if I comment out the arrayCopy function from the assignment operator overload implementation the code also runs fine but off course the object that I am assigning into wont have a copy of the array. The BackTrace also says that the error is on this line:

else if (node->next == nullptr)


Any help is appreciated, Thanks!

HashMap::HashMap()
:hasher{hash}, Buckets_Array{new Node* [initialBucketCount]}, currentBucketCount{initialBucketCount}, sz{0}

{
fillArray(Buckets_Array, currentBucketCount);


}


HashMap::HashMap(const HashMap& hm)
:hasher{hm.hasher}, Buckets_Array{new Node*[hm.currentBucketCount]},currentBucketCount{hm.currentBucketCount}, sz{hm.sz}
{
arrayCopy(hm.Buckets_Array, Buckets_Array, currentBucketCount);

}


HashMap::~HashMap()
{
for(int i = 0; i < currentBucketCount; i++)
{
deleteLinkedList(Buckets_Array[i]);
}

delete[] Buckets_Array;
}


HashMap& HashMap::operator=(const HashMap& hm)
{
if (this != &hm)
{

Node** newNodeArray = new Node*[currentBucketCount];
fillArray(newNodeArray, currentBucketCount);
arrayCopy(hm.Buckets_Array, newNodeArray, currentBucketCount);
currentBucketCount = hm.currentBucketCount;
sz = hm.sz;

for (int i = 0; i < currentBucketCount; i++)
{
deleteLinkedList(Buckets_Array[i]);
}

delete[] Buckets_Array;
Buckets_Array = newNodeArray;

}

return *this;
}

void HashMap::add(const std::string& key, const std::string& value)
{
// REHASH IF EXCEEDED LOAD FACTOR
double futureLoadFactor = double((sz + 1))/double(currentBucketCount);

if (futureLoadFactor > maximumLoadFactor)
{
std:: cout << "REHASHING KEYS....." << std::endl;
rehashKeys();
}

unsigned int index = getIndex(key);

if (!checkExists(Buckets_Array[index], key, value))
{

if (Buckets_Array[index] == nullptr)
{
Node* n = new Node;
n->key = key;
n->value = value;
n->next = nullptr;
Buckets_Array[index] = n;
}

else
{

addToEnd(Buckets_Array[index], key, value);

}

sz += 1;
}


}


Here are some helper member functions that I use:

void HashMap::fillArray(Node** nodeArray, int size)
{
for (int i = 0; i < size; i++)
{
nodeArray[i] = nullptr;
}
}



void HashMap::arrayCopy(Node** source, Node**& target, int arrysz)
{

for (int i = 0; i < arrysz; i++)
{
if (source[i] != nullptr)
{
Node* temp = source[i];
target[i] = temp;
}

else
{
target[i] = nullptr;
}
}


}

void HashMap::deleteLinkedList(Node* node)
{


if (node == nullptr)
{
return;
}
else if (node->next == nullptr)
{
delete node;
}
else
{

Node* next = node->next;
delete node;
deleteLinkedList(next);
}

}

void HashMap::addToEnd(Node*& node, std::string key, std::string value)
{

if ( node == nullptr )
{
Node* n = new Node;
n->key = key;
n->value = value;
n->next = nullptr;
node = n;

}


else
{

addToEnd(node->next, key, value);

}

}


this

HashMap HP;
HashMap HH;
HashMap HP.add("k", "v");
HH = HP;


gives me a "double free or corruption error".

however if I remove the HP.add part the program runs without errors

Answer

In arrayCopy you copy the pointer to an element from one hash map into the other. So, you have the same pointer in two maps, and consequently delete the same object twice.

You need to allocate a new element and copy the data from one object into the other.