Deleting and Freeing an Array of Structs/Objects from Memory

How do I free and delete an array of structs/objects from memory? I tried free and delete, but the values are still there.

I particularly require this C setup to follow and would like to get rid and delete the object array created at some point and perhaps garbage collected.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
void * newObject(int size)
{
	void * newObj;
	if ((newObj = calloc(1, size)) == NULL) {
		exit(EXIT_FAILURE);
	}
	return newObj;
}

struct myVar_s; 
typedef struct myVar_s * myVar;

struct myVar {
	char * name;
        int age;
};

myVar myObject[3];

myObject[0] = newObject(sizeof(struct myVar));
myObject[0]->name = "Foo";
myObject[0]->age = 20;
...
...
myObject[1] = newObject(sizeof(struct myVar));
myObject[2] = newObject(sizeof(struct myVar));

delete myObject???
or
delete myObject[0] ???
delete myObject[1] ???
delete myObject[2] ???


Last edited on
> I tried free and delete, but the values are still there.
Well you used calloc() to allocate the memory, so the correct function to use is free(), as in
 
free(myObject[0]);


The second point is that unless you're using specific kinds of debug allocators, you can "peek behind the curtain" and still see the original data. It's one of the problems which makes 'use-after-free' errors so hard to spot, because hey it works - until it doesn't work.

Examples of debug allocators include features such as
- filling the memory with a recognisable pattern such as 0xCD.
- putting each memory block in its own memory page, then marking the page as invalid after free.
But these debug features are a performance hit, so they're only typically enabled when you're looking for problems.

Don't worry, the memory really is freed. The next time you call malloc/calloc, chances are that memory will be reused for it's new purpose.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <iostream>

struct MyVar
{
    char name[20];
    int age;
};

MyVar* newObject( const int size, MyVar* aArray)
{
    aArray = new MyVar[size];
    
    return aArray;
}

int main()
{
    const int size = 3;
    MyVar* myObject = nullptr;
    myObject = newObject(size, myObject);
    
    strcpy(myObject[0].name, "Foo");
    myObject[0].age = 20;
    
    strcpy(myObject[1].name, "Boo");
    myObject[1].age = 21;
    
    strcpy(myObject[2].name, "Coo");
    myObject[2].age = 22;
// TEST
//    strcpy(myObject[4].name, "Boo");
//    myObject[4].age = 21;
    
    for(int i = 0; i < size; i++)
        std::cout << myObject[i].name << ' ' << myObject[i].age << '\n';
    
    delete[] myObject; // ??
    myObject = nullptr;
    
// TEST?
//    strcpy(myObject[1].name, "Boo");
//    myObject[1].age = 21;
    
//    strcpy(myObject[4].name, "Boo");
//    myObject[4].age = 21;
    
    return 0;
}

Thanks guys!

@salem c

Ok got it. using free now with free()/calloc and delete/malloc works ok.

Thanks for the additional c++11 example againtry, I am getting the same results with using free() on calloc and delete on malloc


Is there a way to cross check it just for logic/condition? I understand that setting the object(s) to NULL crashes the program.

Last edited on
Do NOT mix malloc/free with new/delete and with new[]/delete[]

If you have
p = malloc(n);
then this is your only choice.
free(p);

You're free to choose which allocator you like, but when it comes to freeing the memory, you HAVE to use the correct counterpart function.

If you make just one mistake in your code, then all future bets are off as regards to "it doesn't work".

> For some reason, free(myObject[0]) still does not work
You need to post an actual runnable example showing what you mean.
Is there a way to cross check it just for logic/condition? I understand that setting the object(s) to NULL crashes the program.


All I can suggest is try it.

If you have tried my TESTS by uncommenting them then my whole (sadly hidden) point is they deliberately crash the sytem because they shouldn't exist. I would have been worried if they ran without a hiccup.
:)
You're free to choose which allocator you like, but when it comes to freeing the memory, you HAVE to use the correct counterpart function.

If you make just one mistake in your code, then all future bets are off as regards to "it doesn't work".


Thanks, I got confused. Now I am using malloc and free and it works.


> For some reason, free(myObject[0]) still does not work
You need to post an actual runnable example showing what you mean.


just updated and tested with your new info above and it does work. :)

All I can suggest is try it.

If you have tried my TESTS by uncommenting them then my whole (sadly hidden) point is they deliberately crash the sytem because they shouldn't exist. I would have been worried if they ran without a hiccup.
:)


Yes, I got it and it's now clear. Thanks again. :)

I might just do a try and catch exception as I see this can be a workaround for the crash.


Last edited on
I might just do a try and catch exception as I see this can be a workaround for the crash.

That would be good software engineering - out of bounds, and NULL or nullptr - or invariance - <cassert> - pre and post conditions stuff.

Good luck with it :)
Last edited on
@againtry

Do you know other solutions to check if an object is already deleted?
Last edited on
@ruzip

I understand your concern. Perhaps this helps.

https://stackoverflow.com/questions/15730827/how-to-detect-if-a-pointer-was-deleted-and-securely-delete-it

By assigning the pointer NULL or nullptr you only need check that that is true

Try it
1
2
3
4
5
6
7
    delete[] myObject; // ??
    myObject = nullptr;
    
    if(myObject != nullptr)
        std::cout << "OOPs\n";
    else
        std::cout << myObject << '\n';
Last edited on
@againtry

Thanks, but I am still getting crashes when assigning it to a nullptr and checking it with

myObject != nullptr

I am also trying to delete object items, same result

1
2
delete myObject[1]
myObject[1] = nullptr


Last edited on
1. delete applies to a pointer created using new
2. MyObject[1] is not a pointer, MyObject is
3. My line 19 doesn't rely on new
4. It's not until my line 20 that MyObject (still a pointer) points to an array created using new and therefore delete[] is used

( Don't feel left out though. This is why smart pointers, <vectors> and other STL containers etc etc are used instead of C-style arrays. )

Beyond that, perhaps you should post your latest version.
@againtry

ok thanks, I tried your example with the condition checking that you posted and it returns 0 without crashing which is nice.

Yes, I see that there are smart pointers and vectors now, but I need to solve this with the existing setup or at least make slight modifications using C style arrays.

But eventually yes I would be curious on how this would be setup using vectors with the same application.

How do I safely delete them individually and do some checking and not the whole pointer like MyObject[1]?

btw, I have to use and still using the same setup as I have posted to remove MyObject[i] and check them if it is still possible, but yes thinking about using vectors instead if this can be replicated as close as possible.



Last edited on
How do I safely delete them individually and do some checking and not the whole pointer like MyObject[1]?

You need to understand that MyObject[1] is a MyVar object, not a pointer.

My best advice is for you to read the two tutorials below, particularly the second in relation to your question. It shows how pointers to an array point to the first element ( [0] ) in the array.

You can do pointer arithmetic and travel through the array, but that's another story except this might be useful:
1
2
3
4
5
6
7
8
9
    MyVar* ptr_to_myObject = myObject;
    for(int i = 0; i < size; i++)
    {
        std::cout << ptr_to_myObject -> name << ' ' << myObject -> age << '\n';
        ptr_to_myObject++;
    }
    
    delete[] myObject; // ??
    myObject = nullptr;


http://www.cplusplus.com/doc/tutorial/pointers/
http://www.cplusplus.com/doc/tutorial/dynamic/

PS deleting an individual element (pointer) in an array if it's not impossible, if it's not fraught with danger, would be next to useless. Maybe one half reasonable way would be to copy the array to a new one or shift the elements to fill the gap and update the size.
Last edited on
Thanks for the answers againtry, this really helped.

So skipping the exception workaround and with your additional info, I understand now.

I also have decided to keep it simple for now and since my arrays are fixed in numbers, instead of deleting I think I will just assign them with a new object "reset" again, so in case I do a check for null or value it works..

1
2
3
4
5
6
7
8
9
10
11
12
13
myObject[5] = newObject(); //new
myObject[5]->age = 20;
...
...
...
myObject[5] = newObject(); //decide to reset or "delete"

for(int i = 0; i < size; i++)
{
  if(myObject[i].age != NULL){
    //this does not crash anymore
  }
}


cheers.
Last edited on
1
2
3
4
if(myObject[i].age != NULL)
    std::cout << myObject[i].age << '\n';
else
    std::cout << "NULL encountered\n";


Last word because it's very late for me, but you should try this because it highlights the difference between pointers and the actual object.

Cheers
:)
Yes, I got it now that is why I decided to just to delete and reset the object to new instead so I can do a check if I need to.

I will be for sure transitioning to vectors if I can get some idea on how to replicate a similar setup and since I need to do some additional functions like before, next and after.

Thanks for that last info and example. cheers :)
Last edited on
Topic archived. No new replies allowed.