How to free memory of dynamic struct array

假装没事ソ 提交于 2019-12-23 05:39:04

问题


As someone who never dealt with freeing memory and so on, I got the task to create a dynamic array of struct and create functions to add or delete array elements. When deleting I have to free the memory which is no longer necessary.

when deleting the 2nd element of an array of the size of 3, I move the 3rd element to the 2nd position and then delete the last one. When deleting the last one, I always get an error... Is there anyone who can find an solution for me?

struct myFriend {
    myFriend() {
        number=0;
        hobbys = new char*[10];
    }
    int number;
    char* name;
    char** hobbys;
};
int main() {
    myFriend* friendList = new myFriend[10];

    myFriend* tempFriend = new myFriend;
    tempFriend->number=1;
    tempFriend->name = "ABC";

    myFriend* tempFriend2 = new myFriend;
    tempFriend2->number=2;
    tempFriend->name = "XYZ";

    myFriend* tempFriend3 = new myFriend;
    tempFriend3->number=3;
    tempFriend3->name = "123";

    friendList[0] = *tempFriend;
    friendList[1] = *tempFriend2;
    friendList[2] = *tempFriend3;

    friendList[1] = friendList[2]; //move 3rd element on 2nd position
    delete &(friendList[2]); //and delete 3rd element to free memory
}

回答1:


Why did you create temporary variables? They're not even needed.

If you use std::vector and std::string, the problem you're facing will disappear automatically:

std::vector<myFriend> friendList(10);

friendList[0]->number=1;
friendList[0]->name = "ABC";

friendList[1]->number=2;
friendList[1]->name = "XYZ";

friendList[2]->number=3;
friendList[2]->name = "123";

To make it work, you should redefine your struct as:

struct myFriend {
    int number;
    std::string name;
    std::vector<std::string> hobbys;
};

If you're asked to work with raw pointers, then you should be doing something like this:

struct Friend 
{
    int    number;
    char*  name;
};

Friend * friends = new Friend[3];

friends[0]->number=1;
friends[0]->name = new char[4];
strcpy(friends[0]->name, "ABC");

//similarly for other : friends[1] and friends[2]

//this is how you should be deleting the allocated memory.
delete [] friends[0]->name;
delete [] friends[1]->name;
delete [] friends[2]->name;

delete [] friends; //and finally this!

And if you do any of the following, it would be wrong, and would invoke undefined behavior:

delete friends[2];    //wrong
delete &(friends[2]); //wrong



回答2:


It is impossible to delete a subset from array allocated by new []

myFriend* friendList = new myFriend[10];

You have a single whole array

+------------------------------------------------------------------+
|  friendList[0]  |  friendList[1]  |    .....  |   friendList[9]  | 
+------------------------------------------------------------------+

You can not delete &(friendList[2]). You get from C++ whole array of 10 elements. This array starts from friendList (or &(friendList[0])).

operator delete with pointer to the address returned by new (i.e. friendList) is valid only.




回答3:


Two things I noticed. (1) You are apparently supposed to "create functions to add or delete elements" but you haven't done that, you have only created one function. (2) You are making your work harder than it needs to be by using a struct that also needs to manage memory. I suggest you use a simpler struct.

Your assignment is, in effect, to make a simple 'vector' class, so I suggest that you do that. Start with a struct that is empty. If the teacher requires you to use the myFriend struct as written, you can add that in after you finish making your vector like functions. I'm going to assume that you aren't allowed to make a class yet because most instructors make the mistake of leaving that until last.

struct MyStruct {
    int value; // start with just one value here. Dealing with pointers is more advanced.
};

MyStruct* array;
int size;
int capacity;

void addMyStruct(MyStruct& value); // adds a MyStruct object to the end.
void removeMyStructAtPosition(int position); // removes the MyStruct object that is at 'position'

// I leave the functions for you to implement, it's your homework after all, but I give some clues below.

void addMyStruct(MyStruct& value) {
    // First check that there is enough capacity in your array to hold the new value. 
    // If not, then make a bigger array, and copy all the contents of the old array to the new one.
    // (The first time through, you will also have to create the array.)
    // Next assign the new value to array[size]; and increment size
}

void removeMyStructAtPosition(int position) {
    // If the position is at end (size - 1,) then simply decrement size.
    // Otherwise you have to push all the structs one to the left (array[i] = array[i + 1])
    // from position to the end of the array.
}

int main() {
    // test your new class here.
    // don't forget to delete or delete [] any memory that you newed.
}



回答4:


The array size is fixed at 10, so you don't need to delete any elements from it. But you do need to delete the name and hobbys elements of friendList[1] (and before you overwrite it). There are two problems here:

  1. You are setting friendList[0]->name = "ABC"; Here, "ABC" is a constant zero-terminated string somewhere in memory. You are not allowed to delete it. So you have to make a copy.
  2. You want to delete hobby[i] whenever it was assigned. But in your code, you can't tell whether it was assigned. So you have to set every element to 0 in the constructor, so that you will later know which elements to delete.

The proper place to delete these elements is in myFriends's destructor.




回答5:


It seems the point of the question is to manage a dynamic array. The main problem is that he is using an array of friendList. Use an array of pointers to friendList:

struct myFriend {
    myFriend() {
        number=0;
        hobbys = new char*[10];
    }
    int number;
    char* name;
    char** hobbys;
};
int main() {
    myFriend** friendList = new myFriend*[10];

    myFriend* tempFriend = new myFriend;
    tempFriend->number=1;
    tempFriend->name = "ABC";

    myFriend* tempFriend2 = new myFriend;
    tempFriend2->number=2;
    tempFriend->name = "XYZ";

    myFriend* tempFriend3 = new myFriend;
    tempFriend3->number=3;
    tempFriend3->name = "123";

    friendList[0] = tempFriend;
    friendList[1] = tempFriend2;
    friendList[2] = tempFriend3;

    friendList[1] = friendList[2]; //move 3rd element on 2nd position
    delete friendList[2]; //and delete 3rd element to free memory
}

But everybody else is right -- there are major issues around memory allocation for both 'hobbys' and for 'name' that you need to sort out separately.




回答6:


To do your homework I'd suggest to learn much more about pointers, new/delete operators, new[]/delete[] operators (not to be confused with new/delete operators) and objects creation/copying/constructors/destructors. It is basic C++ features and your task is all about this.

To point some directions:

1) When you dynamically allocate the object like this

MyType* p = new MyType;

or

MyType* p = new MyType(constructor_parameters);

you get the pointer p to the created object (new allocates memory for a single object of type MyType and calls the constructor of that object).

After your work with that object is finished you have to call

delete p;

delete calls the destructor of the object and then frees memory. If you don't call delete your memory is leaked. If you call it more than once the behavior is undefined (likely heap corruption that may lead to program crash - sometimes at very strange moment).

2) When you dynamically allocate array like this

MyType* p = new MyType[n];

you get the pointer p to the array of n created object located sequentially in memory (new[] allocates single block of memory for n objects of type MyType and calls default constructors for every object).

You cannot change the number of elements in this dynamic array. You can only delete it. After your work with that array is finished you have to call

delete[] p;  // not "delete p;"

delete[] calls the destructor of every object in the array and then frees memory. If you don't call delete[] your memory is leaked. If you call it more than once the behavior is undefined (likely program crash). If you call delete instead of delete[] the behavior is undefined (likely destructor called only for the first object and then attempt to free memory block - but could be anything).

3) When you assign the struct/class then operator= is called. If you have no operator= explicitly defined for your struct/class then implicit operator= is generated (it performs assignment of every non-static member of your struct/class).



来源:https://stackoverflow.com/questions/5754864/how-to-free-memory-of-dynamic-struct-array

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!