Delete array pointer? - c++

How do I delete the memory that have been allocated for array models, names? I tried every method but it always crashes when I run it.
int main()
{
vector<Person*> people;
const int PERSON_SZ = 4;
char * names[] = {"Jim", "Fred", "Harry", "Linda"};
int ages[] = { 23, 35, 52, 59 };
for (int i = 0; i < PERSON_SZ; i++)
{
Person * temp = new Person(names[i], ages[i]);
people.push_back(temp);
}
// A vector of Car pointers
vector<Car*> cars;
const int CAR_SZ = 3;
char * models[] = { "Festiva", "Ferrarri", "Prius" };
srand(time(0));
for (int i = 0; i < CAR_SZ; i++)
{
Car * temp = new Car(models[i]);
temp->set_driver(people[rand() % (people.size())]);
temp->set_owner(people[rand() % (people.size())]);
cars.push_back(temp);
}
for (int p = 0; p < people.size(); p++)
{
people[p]->increment_age();
}
for (int c = 0; c < cars.size(); c++)
{
cars[c]->print();
}
delete [] names;
for ( int r = 0; r < CAR_SZ; ++r )
{
delete [] models[r];
}
return 0;
}

You didn't allocate models and names using new, so you cannot delete them.
Both arrays are allocated on the stack and are automatically deleted, when the function returns.
The contents of the (string) arrays (i.e. the strings itselves) are stored in the global data segment and cannot be freed at all. This would also be dangerous because the compiler might use the same string constant at different places in the program.

The models array and the names array are both statically allocated. You didn't use new to create them, you don't need to delete them. You should, however, change their types as follows:
const char * names[] = {"Jim", "Fred", "Harry", "Linda"};
const char * models[] = { "Festiva", "Ferrarri", "Prius" };
because they are pointers to string literals, which are read-only.

The variable names and models are not dynamically allocated, and neither is the data in those arrays. So no need to free them or their contents.
The two vector contains data that need to be free'd on the other hand.

You did not allocate names, and models. You don't need to free or delete them from memory.

As others have answered, this is neither required nor legal...
delete [] names;
Since you didn't new names.
Neither is this...
for ( int r = 0; r < CAR_SZ; ++r )
{
delete [] models[r];
}
Since you didn't new any of the models.
But you do still have some memory leaks!
For each car instance you newed and stored in the cars vector, you need to call delete. Here is one way:
for (std::vector<Car*>::iterator car = cars.begin(), done = cars.end(); car != done; ++car)
{
delete *car;
}
Note that the * there dereferences the iterator, yielding the raw pointer you newed.
The problem with this approach is that it leaves you with a vector full of dangling pointers. You could either reset them in the loop or clear() the vector after the loop has terminated. Perhaps a better approach would be:
while (not cars.empty())
{
delete cars.back();
cars.pop_back();
}
Which deletes each car, then removes its pointer from the vector.
Similarly for each person you newed and stored in people:
while (not people.empty())
{
delete people.back();
people.pop_back();
}
As a rule of thumb, there should be one delete for every new and one delete[] for every new ... []. But you'll do well to learn about smart pointers.

names and models are not pointing heap-allocated area. Don't delete it.

Your code is incomplete. It does not compile. Please enable all warnings and debugging for your compiler, e.g. with g++ -Wall -g if using GCC and improve your code till you get no warning
char * names[] = {"Jim", "Fred", "Harry", "Linda"};
delete [] names;
This is incorrect. You can only delete something that you obtained thru new.

Related

C++ Delete Pointer to array of pointers without deleting the contents [Memory Leak]

I'm writing my own array sorting method and I have created a duplicate array to stored the objects as they are stored. The arrays are both arrays of pointers and so I need to delete my temporary array without deleting the items it points to. In the code snippet below I am leaking memory as I either delete all the items or do not delete anything.
//In constructor initialiser list
m_listArray( new PathFindingTile*[maxSize] )
void sort()
{
auto** sorted = new PathFindingTile*[m_size];
sorted[0] = m_listArray[0];
for (int i = 1; i < m_size; i++)
{
sorted[i] = m_listArray[i];
for (int j = i; j - 1 >= 0; j--)
{
if (*m_listArray[j] < *m_listArray[j - 1])
{
PathFindingTile* temp = sorted[j - 1];
sorted[j - 1] = m_listArray[i];
sorted[j] = temp;
}
else
{
sorted[i] = m_listArray[i];
break;
}
}
}
m_listArray = sorted;
//Both 'delete sorted' and 'delete[] sorted' delete the contents of sorted, but I'd only like to delete the array pointer
delete sorted;
}
How can I transfer the duplicated list back to the original list without leaking memory?
m_listArray = sorted;
On this line, you leak the array that m_listArray was pointing at before the assignment.
You must delete the array before (the only) pointer to it is overwritten. Also, delete is wrong for deleting pointers from new[]. delete[] is correct:
delete[] m_listArray;
m_listArray = sorted;
P.S. It is not a good idea to have bare pointers to owned memory. I recommend using std::vector instead. Also, it should not be necessary to allocate a new array in order to sort one. You could simply swap elements within the array.
I think you just remove pointer to the first element in the array. I believe you need to release the array with the follow command.
delete[] sorted
Read more about delete and delete[] [delete vs delete[]]1

Fix Runtime Error with Reverse Array Code using pointers [duplicate]

How do I delete the memory that have been allocated for array models, names? I tried every method but it always crashes when I run it.
int main()
{
vector<Person*> people;
const int PERSON_SZ = 4;
char * names[] = {"Jim", "Fred", "Harry", "Linda"};
int ages[] = { 23, 35, 52, 59 };
for (int i = 0; i < PERSON_SZ; i++)
{
Person * temp = new Person(names[i], ages[i]);
people.push_back(temp);
}
// A vector of Car pointers
vector<Car*> cars;
const int CAR_SZ = 3;
char * models[] = { "Festiva", "Ferrarri", "Prius" };
srand(time(0));
for (int i = 0; i < CAR_SZ; i++)
{
Car * temp = new Car(models[i]);
temp->set_driver(people[rand() % (people.size())]);
temp->set_owner(people[rand() % (people.size())]);
cars.push_back(temp);
}
for (int p = 0; p < people.size(); p++)
{
people[p]->increment_age();
}
for (int c = 0; c < cars.size(); c++)
{
cars[c]->print();
}
delete [] names;
for ( int r = 0; r < CAR_SZ; ++r )
{
delete [] models[r];
}
return 0;
}
You didn't allocate models and names using new, so you cannot delete them.
Both arrays are allocated on the stack and are automatically deleted, when the function returns.
The contents of the (string) arrays (i.e. the strings itselves) are stored in the global data segment and cannot be freed at all. This would also be dangerous because the compiler might use the same string constant at different places in the program.
The models array and the names array are both statically allocated. You didn't use new to create them, you don't need to delete them. You should, however, change their types as follows:
const char * names[] = {"Jim", "Fred", "Harry", "Linda"};
const char * models[] = { "Festiva", "Ferrarri", "Prius" };
because they are pointers to string literals, which are read-only.
The variable names and models are not dynamically allocated, and neither is the data in those arrays. So no need to free them or their contents.
The two vector contains data that need to be free'd on the other hand.
You did not allocate names, and models. You don't need to free or delete them from memory.
As others have answered, this is neither required nor legal...
delete [] names;
Since you didn't new names.
Neither is this...
for ( int r = 0; r < CAR_SZ; ++r )
{
delete [] models[r];
}
Since you didn't new any of the models.
But you do still have some memory leaks!
For each car instance you newed and stored in the cars vector, you need to call delete. Here is one way:
for (std::vector<Car*>::iterator car = cars.begin(), done = cars.end(); car != done; ++car)
{
delete *car;
}
Note that the * there dereferences the iterator, yielding the raw pointer you newed.
The problem with this approach is that it leaves you with a vector full of dangling pointers. You could either reset them in the loop or clear() the vector after the loop has terminated. Perhaps a better approach would be:
while (not cars.empty())
{
delete cars.back();
cars.pop_back();
}
Which deletes each car, then removes its pointer from the vector.
Similarly for each person you newed and stored in people:
while (not people.empty())
{
delete people.back();
people.pop_back();
}
As a rule of thumb, there should be one delete for every new and one delete[] for every new ... []. But you'll do well to learn about smart pointers.
names and models are not pointing heap-allocated area. Don't delete it.
Your code is incomplete. It does not compile. Please enable all warnings and debugging for your compiler, e.g. with g++ -Wall -g if using GCC and improve your code till you get no warning
char * names[] = {"Jim", "Fred", "Harry", "Linda"};
delete [] names;
This is incorrect. You can only delete something that you obtained thru new.

C++ error on delete[] after iterating through pointer

Environment: Windows 7 pro x64, Microsoft Visual Studio 2015 Enterprise, Version 14.0.25424.00 Update 3
int testFunction()
{
std::string _orig = "[188 80% (1/2)O:152]";
std::string _orig2 = "[999 99% (1/1)O:999]";
char *orig = NULL;
char *orig2 = NULL;
orig = new char[_orig.length() + 1];
strcpy(orig, _orig.c_str());
orig2 = new char[_orig2.length() + 1];
strcpy(orig2, _orig2.c_str());
*orig++;
*orig2++;
int a = atoi(orig);
int b = atoi(orig2);
delete[] orig;
delete[] orig2;
return 0;
}
Running the above code crashes with the "_CrtIsValidHeapPointer(block)" error.
If I don't iterate (*orig++ and *orig2++), then no issues.
So my question is, how can I iterate through the pointers and then when I'm done doing what I need to do with them, delete[] them correctly?
You did not delete the pointers you allocated!
delete must be called on the original memory address returned by new. Since you did orig++, you cant delete the address being pointed at!
Iterating can be done with an index, and using array subscription to dereference:
orig[i] = 'a';
Which is the same as doing this:
*(orig+i) = 'a';
Or you can get another pointer onto the same data, and modify this one.
char* pOrig = orig;
++pOrig;
Why did you write
*orig++; // why dereferencing?
Just ++ by itself would do the iteration.
Avoid to use raw pointers. Your code can be simpler:
std::string orig = "[188 80% (1/2)O:152]";
std::string orig2 = "[999 99% (1/1)O:999]";
int a = atoi(orig.c_str() + 1);
int b = atoi(orig2.c_str() + 1);
Your mistake is that you try to delete the shifted pointers instead of the original pointers. As the result heap manager gets wrong allocated block information usually put before the allocated pointer and you got heap corruption.
how can I iterate through the pointers and then when I'm done doing what I need to do with them, delete[] them correctly?
Create a copy of the pointer:
char* orig = new char[size];
char* i = orig;
*i++ = 'a';
delete orig;
A perhaps more common idiom is to dereference a temporary:
for(int i = 0; i < size - 1; i++)
orig[i] = 'a';
I would love to [use std::string], but I need to use atoi(), which won't work on std::string
You are mistaken. atoi works with std::string just fine. Simply use std::string::c_str() just like you did with strcpy. There is absolutely no reason to allocate a block of memory with new.
int testFunction()
{
std::string _orig = "[188 80% (1/2)O:152]";
int a = 0;
for (std::string::iterator it = _orig.begin(); it != _orig.end(); ++it)
{
if (isdigit((char)*it))
a = (atoi(it._Ptr));
}
return 0;
}
I got it. Thanks for everyone who helped me come to this conclusion. Staying with std::string was in fact the best approach.

C++ resize array of pointer without STL (vector...)

I got following problem.
I want to resize my array of pointers on structure ( car ) . I got following code.
Class Car{
...
char * Owner_Name;
char * carID
};
Class Register {
...
int CarCNT;
int car_num_default;
Car ** dataBase;
Register ()
{ //constructor
car_num_default = 5 ; //for example;
dataBase = new Car * [car_num_default];
}
};
Now when I add 6th. car I need to resize my array of pointer to car. How should I do that without create any memory leak ? Or memory error ? :)
I tried folowing code but it makes some memory leaks..
void Register:: Add ( const char * carID, const char * owner)
{
if (carCNT == car_num_default) // now it's full array need resize
{
car ** tmp = new car * [carCNT]; //create new array ;
for(int i = 0 ; i < carCNT;i++)
tmp[i] = new car(databaze[i]->car_ID,databaze[i]->owner_name);
free(database); //free memory and than alloc new bigger
database = new car * [car_num_default * 5];
for(int i = 0; i < carCNT; i++)
data_by_RZ[i] = tmp [i];
free(tmp);
car_num_def = car_num_def * 5;
}
databaze[carCNT] = new car(....);
carCNT++;
}
Thanks for any help!
Here's a list of obvious bugs in your memory management:
You allocate with new[] but deallocate with free. See Is there any danger in calling free() or delete instead of delete[]?
On reallocation, you create new car instances and copy the data of existing car objects instead of copying the pointers to the existing car obejcts. This causes all the previous cars objects to leak. This bug is only when copying database to the tmp table. The copy from tmp to the new database would be correct if tmp contained the pointers to the old car objects.
You needlessly create a tmp array and copy the database to it. You should simply create the new, bigger array, copy, deallocate the old and then set the database pointer. This bug does not cause a leak, but is entirely pointless and does waste memory bandwidth.*
* Here's the code as requested:
Car** tmp = new Car*[car_num_default * 5];
for(int i = 0; i < CarCNT; i++)
tmp[i] = database[i];
delete[] database;
database = tmp;
Remember that functions destroy their parameters after the function finishes its execution.
Since you are passing carID and owner as pointers and inserting them into the array, the values are destructed after execution and the pointers placed inside the array become invalid causing the leak. Use pointers only when you want to make a change to the pointer itself but never store it as it will soon be destructed.
It seems that you are using pointers in places you shouldnt or where you don't have to. Here is a simpler version of your code that does the same:
Class Car{
...
char Owner_Name;
char carID;
};
Class Register {
...
int CarCNT;
int car_num_default;
Car * dataBase;
Register ()
{ //constructor
car_num_default = 5 ; //for example;
dataBase = new Car [car_num_default];
}
};
void Register:: Add ( const char carID, const char owner)
{
if (CarCNT == car_num_default) // now it's full array need resize
{
car * tmp = new car [carCNT]; //create new array ;
for(int i = 0 ; i < carCNT;i++)
tmp[i] = new car(dataBase[i].car_ID,dataBase[i].owner_name);
free(dataBase); //free memory and than alloc new bigger
dataBase = new car [car_num_default * 5];
for(int i = 0; i < carCNT; i++)
data_by_RZ[i] = tmp [i];
free(tmp);
car_num_def = car_num_def * 5;
}
Car x(...);
dataBase[CarCNT] = x;
carCNT++;
}
Finally, I have four points to make:
1) This doesnt seem like C++ or you are not using proper naming
2) I am not sure how this code complied since most variable names are incorrect (i tried to fix what i came across).
3) Excessive use of pointers (memory locations in other words) is the main cause of memory leaks. Handle them with care and only use them when you have to.
4) IFFF you have to use pointers that much then add destructors (Anti-constructor) like this ~Car or ~Register on any class that is used as a pointer to signal when the element is destroyed. That way you know where the leak is taking place by writing to the console or handle the destruction gracefully.
Hope that helped

Member Variable Of Type String (Array) Pointer throwing Exception. (C++)

I have instantiated a private member variable in a 'Student' object. It points to an array that I'm dynamically resizing according to number of courses the 'student' is enrolled in.
I'm new to pointers, and I'm probably messing up something to do with the reference to the dynamically declared 'course' array in the heap.
EDIT : Vectors, Lists, or anything other than primitive std:string arrays can't be used.
The following line throws an exception:
void Student::addCourse(std::string course){
numCourses++;
std::string *tempArray = new std::string[numCourses];
for(int i = 0; i <= numCourses - 1; i++){
tempArray[i] = courseList[i]; // <---------- This line...
}
tempArray[numCourses - 1] = course;
courseList = tempArray;
delete []tempArray;
}
Unhandled exception at 0x50A0E89A (msvcr110d.dll) in filename.exe:
0xC0000005: Access violation reading location 0xABABABAB.
The member is declared like so in the header file:
class Student
{
private:
std::string *courseList;
EDIT : Here's the constructor I'm using:
Student::Student(std::string name)
:numCourses(0),
courseList(nullptr),
name(name){}
Any input is appreciated.
Cheers.
Why you don't use a list, like:
List<string> s = new List<string>();
Basically what is wrong with your code is the delete []tempArray; and that is, because before that you make courseList point to the same address that tempArray points to, and then you delete memory stored within tempArray, which means that courseList now points to invalid(recycled, freed) memory.
You should make courseList nullptr(NULL if you don't have C++11-compilant compiler) when in constructor, and then the Student::addCourse can look like this:
void Student::addCourse(std::string course){
numCourses++;
std::string *tempArray = new std::string[numCourses];
for(int i = 0; i < numCourses - 1; i++)
{
tempArray[i] = courseList[i];
}
tempArray[numCourses - 1] = course;
delete[] courseList;
courseList = tempArray;
}
So basically you allocate new memory for the new sequence of strings, and then you assign the old contents from courseList into tempArray, then you assign the new course string into the last place, and you delete the old strings. After that you make courseList point to the same thing tempArray points to.
EDIT:
Changed the -2 into -1 as well as <= into <