Deleting a dynamically allocated Array of Pairs throwing invalid address error - c++

I have a very curious problem. I have a custom class Set, and a custom class Map (I have to recreate the standard library implementations for a class). In my map class, I create an array of pair<string, Set<string>>. But, when I expand my array of values and re-hash the values, I want to delete my old array. But, Whenever (and wherever in my code...) I try to, I get a Invalid address specified to RtlValidateHeap error. This happens even when the delete call is on the line after my new[] statement.
I have private class variable I call pair<string, Set<string>> *values;. Then in my constructor I do the following.
values = new pair<string, Set<string>>[tableSize];
Then when I got to delete values in a member function it threw the invalid address error. The code is below - I swap newValues, and values, then delete newValues in the reallocate() function. That is where the error is thrown
Node: the map is functioning perfectly. I can hash, store, and recall values without any errors.
Expanded Code:
template<>
class Map<std::string, Set<string>> : public MapInterface<string,Set<string>>{
public:
Map() {
numItems = 0;
tableSize = BonusHashTableSize;
values = new pair<string, Set<string>>[tableSize];
for (int i = 0; i < tableSize; ++i) {
values[i].first = "";
}
};
~Map() {
for (int i = 0; i < tableSize; ++i) {
if (values[i].first != "") {
values[i].second.clear();
}
}
delete[] values;
};
void reallocate() {
tableSize *= 2;
pair<string, Set<string>> *newValues = new pair<string, Set<string>>[tableSize];
for (int i = 0; i < tableSize; ++i) {
newValues[i].first = "";
newValues[i].second = Set<string>();
}
for (int i = 0; i < tableSize / 2; ++i) {
if (values[i].first != "") {
int newIndex = rehash(newValues, values[i].first);
newValues[newIndex].first = values[i].first;
newValues[newIndex].second = values[i].second;
Set<string> test = newValues[newIndex].second;
}
}
std::swap(values, newValues);
delete[] newValues;
//member functions
private:
pair<string, Set<string>> *values;
int tableSize;
int numItems;
};

Remove delete values from constructor. What is the purpose of allocation if you are just going to delete in the next line? And also you are using the deleted memory in the next for loop block.
Since you have deleted it here , it will cause invalid memory access error anywhere else because you are trying to delete already deleted memory location.

Related

C++ destructor throws error

I have the following code:
class MyList
{
private:
public:
int* list;
int size = 0;
int max;
// constructor
MyList(int s)
{
max = s;
size = 0;
if(max > 0)
list = new int[max];
};
// destructor
~MyList()
{
for (int x = 0; x < max; x++)
delete (list + x);
};
};
I tried to clear the memory with that destructor. However, it throws an error on second iteration. What did I do wrong? Also, it wouldn't let me do it this way:
delete list[x];
Can someone explain to me why? Thank you so much.
You should use delete[] because list is created via new[]-expression. e.g.
// destructor
~MyList()
{
delete[] list;
}
Note that they must be pair; new int[max] create an array containing max's elements, delete[] destroy the whole array. delete should only be used for pointer created by new.
And better to change the constructor to
// constructor
MyList(int s)
{
max = s;
size = 0;
if(max > 0)
list = new int[max];
else
list = nullptr;
}
to make sure list is always valid.
Try this:
MyList(int s)
: max(s),
size(0),
list(new int[s])
{
};
~MyList()
{
delete[] list;
};
i dnt understand why are you using
a loop to deallocate that memory.... you should simpy write
delete[] list;
that would be enough!
in your destructor you are using delete (list(a pointer)+x) this is not deallocating memory you created...
you are tryin to delete addresses next to your list by adding value of x loop in it
i hope you understood your error :)

Class type Segmentation Fault

It has been long time I did not use c++ and I have some basic errors. Can you tell me why I get Segmentation Fault from my generic code?
When I use int as a array type, it works perfectly but when I change it with "Trapdoor" type, it gives me Seg Fault.
array<array<int, colN>, rowN> SmartIds::createMatrix() {
array<array<int, colN> , rowN> a;
for(int i = 0; i < rowN; i++) {
a[i] = createTrapdoors();
}
//sort(a.begin(), a.end());
return a;
}
Below code generates seg fault
array<array<Trapdoor, colN>, rowN> SmartIds::createMatrix() {
array<array<Trapdoor, colN> , rowN> a;
for(int i = 0; i < rowN; i++) {
a[i] = createTrapdoors();
}
//sort(a.begin(), a.end());
return a;
}
I call my function like below;
auto i = createMatrix();
Trapdoor.cpp class
#include "Trapdoor.h"
#include <cryptopp/pwdbased.h>
using namespace std;
Trapdoor::Trapdoor() {
// TODO Auto-generated constructor stub
key = nullptr;
seed = nullptr;
iv = nullptr;
counter = 0;
}
Trapdoor::Trapdoor(byte* keyy, byte* ivv) {
key = keyy;
seed = keyy;
iv = ivv;
counter = 0;
}
Trapdoor::~Trapdoor() {
// TODO Auto-generated destructor stub
delete iv;
delete key;
delete seed;
}
void Trapdoor::deriveKeywithCounter() {
SecByteBlock derived(32);
PKCS5_PBKDF2_HMAC<SHA1> kdf;
//kdf.DeriveKey(derived.data(), derived.size(), 0, (byte*)b->data(), sizeof(b), NULL, 0, 100);
memset(iv, 0x00, CryptoPP::AES::DEFAULT_KEYLENGTH);
counter++;
}
int Trapdoor::getCounter() {
return counter;
}
The Trapdoor class does not have a correct copy-constructor or copy-assignment operator. So when objects are copied by value, the old and the new both have destructor called and pointers are freed twice etc. etc.
It's rarely a good design to have your class be calling delete on things that it did not new. Your code needs to be clear about who is responsible for freeing memory.
Usually, the best solution is to code Trapdoor so that it actually does not require any delete at all; then you do not have to write any special functions. See Rule of three/five/zero. (I will update this post to include a code sample if you show your class definition).

Not able to double the size of an array

I want to resize the array when the rehash function is called, by copying the values of initial dictionary into it and then at last redifining the newdictionary as dictionary
void rehash ()
{
int newsize=2*Size;
node **newdictionary;
newdictionary= new node*[newsize];
//Initialising the dictionary
for (int i = 0;i < newsize;i++)
{
newdictionary[i]->name = "";
newdictionary[i]->value = -1;
}
node **temp=dictionary;
delete [] dictionary;
dictionary=newdictionary;
SIZE=newsize;
for(int i=0;i<SIZE;i++)
{
if(temp[i]->value!= -1)
insertvalue(temp[i]->name,temp[i]->value);
}
delete [] temp;
};
Earlier I have defined insertvalue as:
void insertvalue (string filedata, int code)
{
// tableindex is the position where I want to insert the value
dictionary[tableindex]->name= filedata;
dictionary[tableindex]->value=code;
};
You didn't actually explain what problem(s) you're having, but your code has several issues:
void rehash ()
{
int newsize=2*Size;
node **newdictionary;
newdictionary= new node*[newsize];
At this point, newdictionary is simply an array of uninitialized pointers.
//Initialising the dictionary
for (int i = 0;i < newsize;i++)
{
newdictionary[i]->name = "";
newdictionary[i]->value = -1;
}
So the loop above is trying to access the members of node objects that don't yet exist.
node **temp=dictionary;
delete [] dictionary;
These two lines don't make sense. dictionary and temp point to the same memory. So when you delete dictinoary you've deleted the memory that temp is pointing to.
dictionary=newdictionary;
SIZE=newsize;
for(int i=0;i<SIZE;i++)
{
if(temp[i]->value!= -1)
insertvalue(temp[i]->name,temp[i]->value);
}
Even if you hadn't just deleted the memory out from under temp, you're now trying to access temp from 0 to the new size, not the old size. In other words, this would access temp beyond its bounds.
Those are the major problems that I've noticed in the code so far. You at least need to correct all of them before there's any hope of this working. You probably need to spend some time really stepping through your logic to ensure it makes sense in the end.

Memory leaks from 2d array on heap

I'm having an issue with a lot of memory leaks from a class I've created. The assignment is requires creating a word search puzzle on the heap. I've created my destructor, copy constructor and overload the assignment operator.
I think there must be something wrong with one of these functions, because the final check to ensure it is working is to create objects in a loop, to see if it fails and my function is crashing. I've tried different forms of the destructor and I've tried changing around the copy and assignment operator with no luck. Kind of at a loss, and the lack of warnings is really making it difficult to debug without a proper understanding of the heap.
Any help would be really appreciated!
Here are some functions that are working with the heap.
JumblePuzzle::~JumblePuzzle(){
for (int i = 0; i < size; ++i){
delete jumble[i];
}
delete jumble;
}
JumblePuzzle::JumblePuzzle(string word, string diff){
int i = 0;
toHide = word;
difficulty = diff;
jumble = buildArray();
fillArray();
hideWord();
}
JumblePuzzle::JumblePuzzle(JumblePuzzle& temp){
size = temp.size;
rowPos = temp.rowPos;
colPos = temp.colPos;
direction = temp.direction;
toHide = temp.toHide;
difficulty = temp.difficulty;
jumble = temp.getJumble();
}
JumblePuzzle& JumblePuzzle::operator=(const JumblePuzzle& right){
if (this != &right){
for (int i = 0; i < size; ++i){
delete jumble[i];
}
delete[] jumble;
size = right.size;
rowPos = right.rowPos;
colPos = right.colPos;
direction = right.direction;
toHide = right.toHide;
difficulty = right.difficulty;
jumble = right.getJumble();
}
return *this;
}
charArrayPtr* JumblePuzzle::buildArray() const{
charArrayPtr* array = new char*[size];
for (int i = 0; i < size; ++i){
array[i] = new char[size];
}
return array;
}
Here's the line its failing on.
int loopLimit =20;
for (int i = 0; i < loopLimit; i++)
JumblePuzzle jp("HIDDENWORD", "hard");
Thanks for any possible help!
EDIT:
Here is my .h file as well.
#ifndef JUMBLE_H_
#define JUMBLE_H_
#include <time.h>
#include <cstdlib>
#include <string>
using namespace std;
typedef char* charArrayPtr;
class BadJumbleException {
public:
BadJumbleException(const string&);
string& what();
private:
string message;
};
class JumblePuzzle{
public:
JumblePuzzle(string, string); //simple constructor
JumblePuzzle(JumblePuzzle&); //copy constructor
~JumblePuzzle(); //deconstructor
charArrayPtr* getJumble() const;
JumblePuzzle& operator=(const JumblePuzzle&);
//accessors
int getSize();
int getRowPos();
int getColPos();
char getDirection();
private:
//attributes
int size;
int rowPos;
int colPos;
char direction;
charArrayPtr* jumble;
string toHide;
string difficulty;
void fillArray();
void hideWord();
char randomDirection();
int randomNum(int);
charArrayPtr* buildArray() const;
};
#endif
and my getJumble. It's used to get the actual word search created. Returned a copy rather than the pointer so it cant be modified.
charArrayPtr* JumblePuzzle::getJumble() const{
charArrayPtr* tempJumble = new char*[size];
for (int i = 0; i < size; ++i){
tempJumble[i] = new char[size];
}
for (int i = 0; i < size; i++){
for (int j = 0; j < size; j++){
tempJumble[i][j] = jumble[i][j];
}
}
return tempJumble;
}
There is one major thing wrong with your code, and that is you failed to initialize the "size" member in the JumblePuzzle(string, string) constructor.
There are other things you should do:
1) Create a separate function to destroy the 2d array within the JumblePuzzle class. You seem to be copying the same loops to do this in multiple places. No need for that if you just call a function to do this work.
2) Your assignment and copy constructor are not exception safe. If new[] throws an exception during the creation of the copy, then the original object has invalidated data. In other words, you've destroyed the data, and when you want to create another 2d array, when new[] says "oops", you've destroyed your original data and can't get it back.

Memory leak when resizing dynamic array

Here's my code:
template<class T> class Test
{
public:
int Size = 0;
int Length = 0;
T* Items;
Test() {}
~Test()
{
delete [] Items;
}
void Append(const T& newItem)
{
if (Size + 1 >= Length)
{
Length += 250;
T* old = Items;
Items = new T[Length + 250];
for (int i = 0; i < Size; i++)
Items[i] = old[i];
delete [] old;
}
Items[Size] = newItem;
Size++;
}
};
Test<int> test;
for (int i = 0; i < 500000; i++)
test.Append(i);
I'm populating the dynamic array with 500000 integers which must take just 1-2Mb but it takes about 30Mb. There's no problem if i set the initial size to 500000(i.e. no resizing occurring). The grow value(250) seems to affect the memory somehow, if it's larger(for example 1000) then the memory usage is pretty low. What's wrong?
Typically, when you are reallocating an array, you do not want to modify the actual array until the very last second (to maintain exception safety):
T* temp = new T[new_size];
// assume count is the previous size and count < new_size
std::copy(Items, Items + count, temp);
std::swap(temp, Items);
delete [] temp;
Aside from that, there is nothing visible in your code that would cause a memory leak.
The extra size can possibly be due to other optimizations (being turned off) and/or debugging symbols being turned on. What compiler options are you using (and what compiler)? It should be noted that extra size is not necessarily an indication of a memory leak. Have you run this in a debugger or memory profiler which found a leak?
It should also be noted that std::vector does all of this for you.
Looking at your code, you're going to segfault more so than leak memory due to the fact that calling delete or delete[] on a non-NULL, but previously deallocated, pointer is a Bad Thing. Also, I don't believe this is your real code, because what you posted won't compile.
When you delete a pointer, always set it to NULL afterwards. It's good practice to initialize to NULL as well. Let's fix up your code to make sure we don't call delete on previously deallocated pointers. Also, let's initialize our pointer to NULL.
Your misuse of memory probably stems from the following lines of code:
Length += 250;
T* old = Items;
Items = new T[Length + 250];
Notice that you increment Length by 250, but then allocate Length+250 more elements? Let's fix that, too.
template<class T>
class Test
{
public:
int Size;
int Length;
T* Items;
Test() : Size(0), Length(0), Items(NULL){}
~Test() {
if (Items != NULL)
delete [] Items;
}
void Append(const T& newItem)
{
if (Size + 1 >= Length)
{
Length += 250;
T* old = Items;
Items = new T[Length];
for (int i = 0; i < Size; i++)
Items[i] = old[i];
delete [] old;
old = NULL;
}
Items[Size] = newItem;
Size++;
}
};
int main(){
Test<int> test;
for (int i = 0; i < 500000; i++)
test.Append(i);
}