c++ pointer being freed was not allocated error - c++

I am practcing c++'s new/delete, hashfunction and linked.
I made a practice by myself.
I have a struct which is
typedef struct student
{
int id;
string fName;
string lName;
student * nextStudent;
}Student;
Then in main function, I define an array of student
Student * table = new Student [10];
I have my own hash function which takes the id, and change to 0-9.
I want to add a student I do following
void addStudent(int studentId, string firstName, string lastName, Student *table)
{
// using hash function, convert the id into hashed id
int hashedID = hashFunction( studentId );
Student * pointer = &table[hashedID];
while(pointer->nextStudent !=NULL){
pointer = pointer->nextStudent;
}
// once we reach to the student who has NULL in nextStudent
// add student
Student *tmp = new Student;
tmp->id = studentId;
tmp->fName = firstName;
tmp->lName = lastName;
tmp->nextStudent = NULL;
// link
pointer->nextStudent = tmp;
}
I tested it, it seems fine.
The problem is deletion.
Since student variables are stored in dynamic memeory,
I need to use delete.
The following is my code.
void deleteAll(Student *table, int len)
{
for (int i = 0; i < len; i++)
{
Student* tmp = &table[i];
// delete student info except the last one
while ( tmp -> nextStudent !=NULL){
Student* tmp2;
tmp2 = tmp;
tmp = tmp->nextStudent;
delete tmp2;
}
}
}
I visited every student varialbes ane do the deletion.
I cannot find any probelm in my deletion funtion...
This is what I got after run..
malloc: *** error for object 0x7f85f1404b18: pointer being freed was not allocated
I have no clue what I have done wrong..
Can you help me?
EDIT...
As you guys metion
I added "delete [] table" in the main funtion..
Also, I remove "delete tmp" in deleteAll function; i think "delete [] table" will handle that part.
Still does not work..
By the way I forgot to added initTable function in the initial post.
initTable initialize the table...
void initTable (Student *table, int len)
{
for (int i = 0; i < len; ++i)
{
table[i].nextStudent = NULL;
}
}
Thank you.

The nextStudent field is never initialized, so all 10 elements created here have it pointing to unknown values.
Student * table = new Student [10];
This causes addStudent to loop until some pointer->nextStudent hits a NULL value by chance, then overwrite memory it doesn't own (unless it hits the lucky NULL on the first iteration).
while(pointer->nextStudent !=NULL) { ... }
The 'student` struct (btw, why the typedef?) should have a constructor to at least do this.
student::student() : nextStudent(NULL) { }
[ EDIT ] The other issue that #JonathanPotter duly pointed in a comment is that the head of each of the 10 student lists is a member of the table array. It is not dynamically allocated, and should not be individually deleted.
The qucik/easy fix would be to add a student destructor to recursively delete child nodes:
student::~student() { if(nextStudent) delete nextStudent; }
Then deleteAll would reduce to:
void deleteAll(student *table, int len)
{
for (int i = 0; i < len; i++)
{
student *tmp = &table[i];
if(tmp->nextStudent) delete tmp->nextStudent;
}
// this leaves the dynamically allocated table[] in place
// to delete it as well, just `delete [] table;`
}
However, such recursion may become impracticable once the lists grow large, and should better be rewritten as an iteration (without the recursive destructor).
student::~student() { }
// ...
void deleteAll(student *table, int len)
{
for(int i = 0; i < len; i++)
{
student *tmp = &table[i];
// delete student info except the *first* one
for(student *tmp2; tmp2 = tmp->nextStudent; )
{
tmp->nextStudent = tmp2->nextStudent;
delete tmp2;
}
}
// this leaves the dynamically allocated table[] in place
// to delete it as well, just `delete [] table;`
}

Then in main function, I define an array of student
Student * table = new Student [10];
First of all you are creating array of Student not Student*. And late you are trying to delete not allocated values. This is the reason of your program behavior.
To create pointer of array of pointers Student* you need the following:
Student** table = new Student*[10];
Than change your functions arguments from Student* table to Student** table and continue research.
Also do not forget to delete table using delete[] table;
Good Luck.

Related

Array is not resizing with operator new [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 12 months ago.
Improve this question
I want to implement a dynamic array as a class.
I haven written a method which adds an element at the end of the array:
void DynamicArray::addElementAtEnd() {
cout << "\nPodaj liczbe calkowita: ";
int* number = new int;
cin >> *number;
if (DynamicArray::array == NULL) {
DynamicArray::array = new int[1];
DynamicArray::array[0] = *number;
delete number;
(*DynamicArray::size)++;
return;
}
int* buff = new int[*DynamicArray::size + 1];
memcpy(buff, DynamicArray::array, (*DynamicArray::size) * sizeof(int));
delete[] DynamicArray::array;
buff[(*DynamicArray::size)] = *number;
DynamicArray::array = buff;
(*DynamicArray::size)++;
delete number;
return;
};
Here's the .h file of the DynamicArray class:
#include <iostream>
using namespace std;
class DynamicArray {
public:
int* array;
int* size;
public:
DynamicArray() {
DynamicArray::size = new int;
*DynamicArray::size = 0;
};
void handleMenu();
void readFromFile();
void addElementAtEnd();
void addElementAtBeginning();
void addAtIndex(int index);
void deleteElementAtEnd();
void deleteElementAtBeginning();
void deleteElementByIndex(int index);
void showAllElements();
void showElementAtIndex(int index);
void findElementByValue(int value);
};
The problem is that this method adds only the first element, but if I try to add more then nothing happens. I debugged it, and the problem starts on this line:
int* buff = new int[*DynamicArray::size + 1];
I don't know why, but it seems like this line is not creating a bigger array.
I searched for some solutions, and it seems that the problem is connected with using *DynamicArray::size + 1 instead of eg a variable, or I don't do something right with it.
The actual problem is that you are not initializing array to NULL.
So when you check if array is NULL on the first iteration, it is often not.
The minimal solution:
DynamicArray::DynamicArray() {
this->size = 0; // You should use 'size' like an int, not a pointer
this->array = NULL;
}
// Or using the Member Initializer List (by #user4581301)
DynamicArray::DynamicArray(): size(0), array(nullptr) {}
Note: Differences between NULL and nullptr
Other simple solution could be to check if size is equal to 0 instead of checking if array is NULL.
The above change will solve your problem but your code can still be improved.
Take into account the comments of other users.
And make sure to free each dynamically allocated memory.
Let's address a variety of things.
class DynamicArray {
public:
int* array;
int* size;
public:
DynamicArray() {
DynamicArray::size = new int;
*DynamicArray::size = 0;
}
};
A few things here. First, as others have suggested, there's zero reason to make size a pointer.
Next, it's a strong guideline / good idea to always initialize your fields when declared.
So this section of code can look like this:
class DynamicArray {
public:
int* array = nullptr;
int size = 0;
public:
DynamicArray() {
}
};
After that, please use nullptr instead of NULL. NULL is from C, but the correct value in C++ is nullptr.
Now, let's look at this bit of code.
void DynamicArray::addElementAtEnd() {
cout << "\nPodaj liczbe calkowita: ";
int* number = new int;
cin >> *number;
if (DynamicArray::array == NULL) {
DynamicArray::array = new int[1];
DynamicArray::array[0] = *number;
delete number;
(*DynamicArray::size)++;
return;
}
int* buff = new int[*DynamicArray::size + 1];
memcpy(buff, DynamicArray::array, (*DynamicArray::size) * sizeof(int));
delete[] DynamicArray::array;
buff[(*DynamicArray::size)] = *number;
DynamicArray::array = buff;
(*DynamicArray::size)++;
delete number;
return;
};
Aside from the extra colon on the end of the function (entirely not necessary), this is far more complicated than it needs to be. First, get rid of the int pointer. That's just ridiculous.
void DynamicArray::addElementAtEnd() {
cout << "\nPodaj liczbe calkowita: ";
int number = 0;
cin >> number;
int * newArray = new int[size + 1];
newArray[size] = number;
if (array != nullptr) {
for (int index = 0; index < size; ++index) {
newArray[index] = array[index];
}
delete [] array;
}
array = newArray;
++size;
}
A last comment -- it would make far more sense to pass in the new value as an argument to the method, and the calling test code should get the value you're adding. But you're just learning, so this works.
Note also that you shouldn't specify the class the way you have: DynamicArray::array. No one does that. Do it the way I did above.

New to C++, program not responding when dereferencing part of a vector?

I learned C++ yesterday an I'm trying to solve USACO training problems.
http://train.usaco.org/usacoprob2?a=iKSzALidh4Q&S=gift1
For this one, I have created a vector of People pointers. However, after some troubleshooting, I discovered that when I try to do something like
Person bob = *(people.at(i));
or
people.at(i) -> setbalance(giveself); // giveself is an int
The program is not responding and:
Process terminated with status -1073741819 (0 minute(s), 3 second(s).
I'm also new to this forum.
Here is my code:
include statments
using namespace std;
class Person
{
private:
int balance;
int origbalance;
string name;
public:
int getbalance() {return balance;}
string getname() {return name;}
void setbalance(int b){balance +=b;}
void setorigbalance(int o) {origbalance = o;}
int getorigbalance() {return origbalance;}
void giveTo(int num, Person* y) {y->setbalance(num);}
~Person();
Person(string n);
};
Person::Person(string n)
{
name = n;
}
Person::~Person()
{
}
int main()
{
ofstream fout ("gift1.out");
ifstream fin ("gift1.in");
int NP;
fin>>NP;
cout<<NP<<endl;
vector<Person*> people(NP);
cout<<"Created vector\n"<<endl;
for(int i = 0; i<NP; i++)
{
string nam;
fin>>nam;
Person* p = new Person(nam);
people.push_back(p);
cout<<nam<<endl;
}
cout<<"\nFilled vector, size = "<<people.size()<<endl;
for(int i = 0; i<NP; i++)
{
string temp;
fin>>temp;
cout<<"\nNow receiving "<<temp<<endl;
int togive, numgiving;
fin>>togive>>numgiving;
cout<<"\n"<<temp<<" is dividing "<<togive<<" among "<<numgiving<<" people"<<endl;
Person bob = *(people.at(i));
cout<<"hi bob"<<endl;
//(*people.at(i)).setorigbalance(togive);
cout<<"Original balance set"<<endl;
int giveeach = togive/numgiving;
cout<<"or "<<giveeach<<" to each person"<<endl;
int giveself = togive%numgiving;
cout<<"and "<<giveself<<" to himself :/"<<endl;
people.at(i) -> setbalance(giveself);
for(int j=0; j<numgiving; j++)
{
string nametogiveto;
fin>> nametogiveto;
cout<<nametogiveto<<endl;
for(int k=0; k<NP; k++)
{
string namy = people.at(k)->getname();
if(namy==nametogiveto)
{
cout<<"\nHere you go "<<namy<<" have "<<giveeach<<endl;
people.at(k)->setbalance(giveeach);
people.at(i)->setbalance(-giveeach);
break;
}
}
}
}
for(int i=0; i<NP; i++)
{
cout<<people.at(i)->getname()<<endl;;
cout<<people.at(i)->getorigbalance() - people.at(i)->getbalance()<<endl;
cout<<endl;
fout<<people.at(i)->getname();
fout<<people.at(i)->getorigbalance() - people.at(i)->getbalance()<<endl;
}
return 0;
}
You're running into undefined behavior due to dereferencing null pointers.
vector<Person*> people(NP);
This line creates the vector with NP null pointers. You later add on your actual pointers but only ever access the first NP elements which are the null pointers.
That said you don't even need pointers here and I'd recommend getting rid of them. In fact you have memory leaks due to allocating pointers with new but never calling delete on them. In my experience it's typical for people just starting out with C++ to overuse pointers, so think about ways to avoid them first.
Change
vector<Person*> people(NP);
to
vector<Person> people;
and fill it using:
for(int i = 0; i<NP; i++)
{
string nam;
fin>>nam;
Person p(nam); // no more need for pointer or new here
people.push_back(p);
cout<<nam<<endl;
}
later when accessing it you don't need any dereferencing anymore either. That means you can get rid of all the * for example:
Person bob = *(people.at(i));
turns into:
Person bob = people.at(i);
and you can access member functions with . instead of -> everywhere, for example:
people.at(k)->setbalance(giveeach);
would turn into:
people.at(k).setbalance(giveeach);
This means getting rid of a lot of unneeded dereferencing of pointers and also of the memory leak you previously would have had.
For me, it seems that you are getting that error since opening input file fin is not successful. To check it, add the following line after you define fin variable:
ifstream fin ("gift1.in");
if(!fin) {
cout << "Error opening input file.\n";
}
In any case, it's always a good practice to check if the file is opened successfully.

Linked list of pointers C++

I have a list, but now I have to link it.
Here is my program ( I deleted code inside functions, to make my program more easy to read ).
#include <iostream>
using namespace std;
struct Student
{
char ime[16];
char priimek[16];
char vpisna[10];
char ocenaRV[10];
char ocenaDN[10];
char ocenaKV[10];
char ocenaVI[10];
Student *next;
};
void clean(Student* pointer,int x) // Delete random data
{
}
void dodajanje(int x,Student* s) // Add information about student
{
}
void brisi(Student* pointer,int x) // Delete information about student
{
}
int main()
{
int student,mesto, brisanje, ali = 0;
cout << "Number of students?." << endl;
cin >> student;
Student* s = new Student[student];
clean(s,student);
cout << endl;
cout << "Add student to i place in array." << endl;
cin >> mesto;
dodajanje( mesto, s );
for(int i=0;i<(student*2);i++)
{
cout << "add student = 1, delete student = 2, cout information = 3"<<endl;
cin>>ali;
if (ali == 1)
{
cout << endl;
cout << "Add student to i place in array." << endl;
cin >> mesto;
dodajanje( mesto, s );
}
else if (ali == 2)
{
cout << "delete student on i place ?" << endl;
cin >> brisanje;
brisi(s,brisanje);
}
else
{
break;
}
}
delete[] s;
return 0;
}
Can someone explain me how to link my list, because code in all tutorials I came across was similar to this:
Node* temp = Node();
But in my program my code is:
Student* s = new Student[student];
And now I'm lost;
Note: I have to create dynamically linked list.
Node* temp = Node();
This creates a single Node instance. Though it should be this instead:
Node* temp = new Node;
Student* s = new Student[student];
This creates an array of student number of Student instances. This defeats the purpose of a linked list , as you won't be able to add/remove Student instances from the array efficiently. But, just for the sake of argument, lets say you really need an array. You can "link" the Student instances together like this:
for (int i = 0; i < (student-1); i++)
s[i].next = &s[i+1];
s[student-1].next = NULL;
If you actually need a linked list then you need something more like this instead:
Student *studentList = NULL;
Student *lastStudent = NULL;
for (int i = 0; i < student; ++i)
{
Student* s = new Student;
s->next = NULL;
if (lastStudent) lastStudent->next = s;
if (!studentList) studentList = s;
lastStudent = s;
}
// use studentList as needed...
Student *s = studentList;
while (s)
{
Student *next = s->next;
delete s;
s = next;
}
After fixing that, consider using the STL std::list class instead, or even std::forward_list in C++11.
That being said, you also need to rethink your code design. A linked list grows and shrinks dynamically, so there is no point in asking the user for the number of students up front, or pre-allocating the list with garbage that has to be cleaned before it can be used. Change your loop to run forever (or at least until the user says to stop). On each iteration, ask the user what to do. If Add, add a new Student to the list at that time. If Delete, ask the user which student to delete, find that Student, unlink it, and delete it. If Display, ask the user which student to display, find that Student, and display it. And so on.
Linked list is a node based data structure. What you are trying to do is creating a dynamic array of students not a linked list.
If you really need to create a linked list, in place of following line
Student* s = new Student[student];
you should create a nodes as follows in number of time of students in a for loop and link each other by updating student()-> next= next_student (Psuedo code)
Student* s = new Student;
And at end, you have to call delete s within a for loop to deallocate the memory.

A pointer to an array of pointers

I know I should know this, but it's late and my brain just won't put the pieces together.
This is as straight forward as a question can get:
I have a struct item. I want to create a pointer to an array of pointers to that item type.
Eg.
struct item {
int data;
string moreData;
};
I want to have an ArrayPointer that point's to an array. I want that array to contain in each element a pointer to an item.
How do I do this in C++, or more sepcifically where do I need to put how many dereferencing operators? I know how to declare basic (single indirection) pointers and am pretty fluent in their use.
I need information for the following steps if at all possible:
Declaring the ArrayPointer.
Initializing the ArrayPointer with a size s.
Initializing each element of ArrayPointer with new item.
eg:
for(int i = 0; i < s; i++)
ArrayPointer[i] = // a new item
I feel like as soon as someone posts an answer I'm going to facepalm so hard I break my nose.
If I have understood correctly then you need something like this
item **ArrayPointer = new item *[s];
for ( int i = 0; i < s; i++ )
{
ArrayPointer[i] = new item; { i, "More Data" };
}
Or
item **ArrayPointer = new item *[s];
for ( int i = 0; i < s; i++ )
{
ArrayPointer[i] = new item;
ArrayPointer[i]->data = i;
ArrayPointer[i]->moreData = "More Data";
}
To free the allocated memory you can in reverse order
for ( int i = 0; i < s; i++ )
{
delete ArrayPointer[i];
}
delete [] ArrayPointer;
Otherewise if s is a constant then you may simply declare an array of pointers. For example
item * ArrayPointer[s];
for ( int i = 0; i < s; i++ )
{
ArrayPointer[i]->data = i;
ArrayPointer[i]->moreData = "More Data";
}
file.h
struct item {
int data;
string moreData;
};
item ** array;
file.cpp
array = new item*[s];
for(int i = 0; i < s; i++)
{
array[i] = new item;
array[i]->data = 10;
array[i]->moreData = "data";
}
What you want is an array of struct item *, which are pointers to item structs.
An array of such pointers is a struct item **.
#include <string>
#include <cstdlib>
using namespace std;
struct item {
int data;
string moreData;
};
struct item * newItem(int data, string moreData) {
struct item *result = (struct item *) malloc(sizeof(struct item));
result->data = data;
result->moreData = moreData;
return result;
}
struct item ** array; // We don't know the size of the array in advance.
int main() {
int arraySize = 3; // We get this value from somewhere (user input?).
array = (struct item **) malloc(3*sizeof(struct item *));
// Now the array has been allocated. There is space for
// arraySize pointers.
array[0] = newItem(5, "ant"); // Let's make some items. Note that
array[1] = newItem(90, "bear"); // newItem() returns a pointer to
array[2] = newItem(25, "cat"); // an item.
return 0;
}

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.