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 :)
Related
Here is a class definition:
class Person {
private:
char* name;
int numChildren;
Person** childrenList;
public:
Person(char* name);
~Person();
};
In the Person::Person() constructor, it will set up the name of the person based on the constructor parameter, and then create Person object for each child, and each child may have other children. And let's say for one case, after I run this: Person* me = new Person("Alex");, the following structure will be created:
ie if me is created, me's children will also be recursively created.
But I have a trouble in the Person::~Person() destructor. In the destructor it should delete all dynamic objects including name and every child. Here is my attempt:
Person::~Person() {
for (int i = 0; i < numChildren; i++) {
// go inside each child
}
delete[] this->name;
delete[] childrenList;
}
But I don't know how to go inside each child, and the destructor has no parameter.
Could anyone give me some hint? Thanks!
Just delete each child before you delete[] childrenlist :
Person::~Person()
{
for (int i = 0; i < numChildren; i++) {
delete childrenList[i];
}
delete[] childrenList;
...
}
when using a double poiner like Person** childrenList, you have to do this to allocate and delete it:
unsigned len1 = 100;
unsigned len2 = 100;
// childrenList is a pointer to a an array of pointers
Person** childrenList = nullptr;
// create an array with UNALLOCATED Person pointers, note the "*"
childrenList = new Person*[len1];
// allocate all the pointers in the the array
for (size_t i1 = 0; i1 < len1; i1++)
childrenList[i1] = new Person;
// delete all the pointer in the array
for (size_t i1 = 0; i1 < len1; i1++)
if (childrenList[i1])
delete childrenList[i1];
// delete the array itself
delete[] childrenList;
you could put this in your destructor:
Person::~Person()
{
// delete all the pointer in the array
for (size_t i1 = 0; i1 < len1; i1++)
if (childrenList[i1])
delete childrenList[i1];
// delete the list itself
delete[] childrenList;
}
But this whole thing would be done easier with a "2d" std::vector:
vec<vec<Person>> childrenList;
Such a 2d vector has its own syntax, but it is easier and less error prone than "bare" pointers/arrays.-
PS: I have NOT tried to compile or run this example.
My problem seems to be answered with only single pointers. I'm trying to dynamically allocate for a 2d linked list. The problem I ran into when I'm trying to use class llist constructor to set head and tail pointer to NULL :
//I've included only the parts that I see are neccesary
struct node {
int value ;
int weight ;
node* next ;
} ;
class llist{
private :
node* tail, *head ;
public :
llist(){tail = NULL ; head = NULL ;} /* this unneccesary retype is to make sure
that it wasn't a typo*/
}
class list_graph
{
private :
int size, s;
llist ** v ;
public :
list_graph(int s){
this -> s = s ;
size = 0 ;
v = new llist* [s] ;
}
}
I've use the debugger and ran through every steps and it seems that my constructor for llist is not called after I create a object of list_graph type, so every other function that relies on this fails and gives me segmentation fault. Is there anything I'm doing wrong, or is there any workarounds beside using the STL list, many thanks
This:
v = new llist* [s] ;
creates an array of pointers to type llist, but it doesn't create any llist objects. If you want an array of such things, then you want:
llist * v ;
and:
v = new llist[s] ;
Or better still, if this is not a homework assignment, use std::vector. And don't think of things like llist ** v as "double pointers"; think of them as what they are - pointers to pointers.
If you want to allocate a 2D pointer array, you can do it a couple ways:
Using a dynamic array of pointer arrays, given some width and height:
llist** data = new llist*[width];
for (int i = 0; i < width; ++i){
data[i] = new llist[height]; // constructors get called here
}
// accessing a linked list, make sure x is in [0, width) and y is in [0, height):
data[x][y]->value;
Using a single pointer array:
llist* data = new llist[width * height]; // constructors get called here
// accessing a linked list:
// again, make sure x is in [0, width) and y is in [0, height)
data[x + (y * width)]->value;
If you want to keep v as a array of pointers to llist objects, as opposed to an array of llist objects (suggested by Neil Butterworth), dynamically allocate each pointer by changing your list_graph constructor to
list_graph(int s) : size(0), s(s), v(new llist* [s]) {
for (int i(0); i < s; ++i)
v[i] = new llist();
}
EDIT: To avoid calling new s times in the for loop, you could pre-allocate all s llist objects at once. However, this would mean they can not be deleted individually. Your class would look like
class list_graph {
int size, s;
llist* buffer;
llist ** v ;
public:
list_graph(int s) : size(0), s(s),
buffer(new llist[s]), v(new llist* [s]) {
for (int i(0); i < s; ++i)
v[i] = &buffer[i];
}
~list_graph() {
delete[] v;
delete[] buffer;
}
};
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);
}
I have a list of pointer object *lst[200];
I use this to add one to it:
object a = new object();
a->id = current_amount;
lst[current_amount] = a;
current_amount++;
now I want to add a function delete it:
I simply want to remove this element from array: (I store an id use it to delete it)
void delete(object *elem)
{
if(!elem)
return;
for (int i = elem->id ; i < current_amount - 1;i++)
{
lst[i] = lst[i + 1];
}
}
Question: When to call delete elem? The code above doesn't free the memory at all...
void deleteElem(object *elem) // you can't call your function 'delete'
{
if(!elem)
return;
for (int i = elem->id ; i < current_amount - 1;i++)
{
lst[i] = lst[i + 1];
}
delete elem; // this free's the memory
}
Since the code above isn't C++, here's some that is:
std::list<std::unique_ptr<object>> lst;
and the methods erase, push_back, push_front.
I need a double pointer of type DizzyCreature (my class) to point to an array of DizzyCreature pointers. When I run it I get "Access violation reading location 0x...". I can make a DizzyCreature* and call its member functions just fine, but when cannot run through the array and do the same thing for each obj.
I am following these instructions:
http://www.cplusplus.com/forum/beginner/10377/
Code
Server.h:
class Server
{
public:
Server(int x, int y, int count);
~Server(void);
void tick();
private:
DizzyCreature** dcArrPtr;
DizzyCreature* dcPtr;
int _count;
};
Server.cpp:
Server::Server(int x, int y, int count)
{
dcPtr = new DizzyCreature[count]; // this works just fine
dcArrPtr = new DizzyCreature*[count]; // this doesn't (but gets past this line)
_count = count;
}
Server::~Server(void)
{
delete[] *dcArrPtr;
delete[] dcPtr;
}
void Server::tick()
{
dcPtr->takeTurn(); // just fine
for (int i = 0; i < _count; i++) {
dcArrPtr[i]->takeTurn(); // crash and burn
}
}
EDIT:
The member function takeTurn() is in a parent class of DizzyCreature. The program makes it into the function, but as soon as it attempts to change a private member variable the exception is thrown. If it matters, DizzyCreature is of type GameCreature and WhirlyB as this is an assignment on MI.
You have allocated space for dcArrPtr, but didn't allocate every object in this array. You must do following:
Server::Server(int x, int y, int count)
{
dcPtr = new DizzyCreature[count];
dcArrPtr = new DizzyCreature*[count];
for ( int i = 0; i < count; i++ ) {
dcArrPtr[ i ] = new DizzyCreature;
}
_count = count;
}
Server::~Server(void)
{
for ( int i = 0; i < count; i++ ) {
delete dcArrPtr[ i ];
}
delete[] *dcArrPtr;
delete[] dcPtr;
}
This:
dcPtr = new DizzyCreature[count];
"creates" an array of DizzyCreatures, whereas:
dcArrPtr = new DizzyCreature*[count];
"creates" an array of pointers to DizzyCreatures, but crucially doesn't create instances for those pointers to point to.
The preferred solution is to use a standard container for tasks like this anyway though. If you really want to do it like this (and are aware that it's not best practice to do this manually) then you'll need a loop to call new for eachelement in the array of pointers.
You allocate an array of count pointers instead of an array of count objects.
Instead of
dcArrPtr = new DizzyCreature*[count];
you might want to
dcArrPtr = new DizzyCreature[count];
You're allocating an array of pointers, but those pointers aren't valid until you set them to something.
double **arr = new double*[10];
for(int i=0;i<10;++i) {
arr[i] = new double[10];
}
That said, when starting out with C++ you should probably avoid raw arrays and instead use std::array and std::vector:
class Server
{
public:
Server(int x, int y, int count);
void tick();
private:
std::vector<std::vector<DizzyCreature>> dcArrPtr;
std::vector<DizzyCreature> dcPtr;
};
Server::Server(int x, int y, int count)
{
dcPtr.resize(count);
dcArrPtr.resize(count);
}
void Server::tick()
{
dcPtr[0].takeTurn();
for (int i = 0; i < dcArrPtr.size(); i++) {
dcArrPtr[i][0].takeTurn();
}
}
Use a
std::vector<std::vector<DizzyCreature>>
Furthermore, if you want to use raw pointers (which I do not recommend), you'll have to allocate memory for each pointer in your array.
class A
{
std::vector<std::vector<int>> v_;
public:
A()
: v_(500, std::vector<int>(500))
{} // 500 x 500
};
class B
{
int** v_;
public:
B()
: v_(new int*[500])
{ // not even exception safe
for (int i = 500; i--; )
v_[i] = new int[500];
}
~B()
{
for (int i = 500; i--; )
delete[] v_[i];
delete[] v_;
}
};
If you would have seen the implementation of dynamic memory allocation of 2-Dimensional array . That would have given you a better insight of how to proceed in such cases . Most of the answers has already answered you what to do . But just go through any link and see how is memory allocated in case of 2-D array . That Will also help you .