Understanding the difference between free and delete

Hi everyone.

Reading "The C++ Programming Language", I've read that the basic difference between new/malloc and malloc/delete is that with the letters we do not invoke constructor/destructor. I know that in C++ I should try to avoid them malloc/free much as possible, but I want to understand in details the difference between free and delete.

In particular, I want to clearly see the distinction between free the memory and call the destructor.


I built the following code:

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
#include <iostream>
#include <vector>

template <typename T>
std::ostream &operator<<(std::ostream &os, const std::vector<T> &v)
{
    for (auto &x : v)
    {
        os << x << "\n";
    }
    return os;
}

int main()
{

    {
        std::vector<double> *ptv = static_cast<std::vector<double> *>(malloc(sizeof(std::vector<double>))); //24(=3*8) bytes on the heap
        ptv = new(ptv) std::vector<double>{};
        ptv->push_back(96.5);
        ptv->push_back(96.5);

        ptv->~vector(); //calling the destructor of the vector pointed to by ptr
        std::free(ptv); //free the memory owned by ptv
        std::cout << *ptv << std::endl;
    }

return 0;
}




Question 1):

- If I comment line 23 but leave uncommented line 22, 24 bytes are lost, because I'm not releasing the raw memory I allocated with malloc. Calling the destructor of vector, allows me to clear the content of my vector on the heap

- If I comment line 22 but leave uncommented line 23, the 24 bytes allocated with malloc are released, but the 16 bytes corresponding to 2 doubles on the heap are not released. In practice, the vector has not been destroyed and, indeed, they are printed to the screen.

Are my explanations of those leaks correct?



Question 2): Can we say that free acts on the pointer variable, while the destructor really acts on the object itself (the vector on the heap)?


Last edited on
Hi,

In my mind it is simple: malloc and free work together; new and delete work together -> don't mix them. And try to avoid both of them in C++ programs. In the case of malloc, it initialises variables and structures that free explicitly uses to free memory. You should search for the code for these, then you will able to see how it works.

With RAII containers like those found in the STL, one can get away with simply letting the object go out of scope, the cleanup is taken care of automatically. So no need to call destructors, these will be called implicitly anyway.

There may be situations where one may need to write their own destructor, but I don't have enough experience to know when to do that.

Hopefully you are aware that STL containers allocate their own memory on the heap? This makes your example code a very contrived mixture of C and C++.
@TheIdeasMan

Thanks for your answer. As I said at the beginning, I know already the "take-home message" with malloc/free, but I wanted to see the distinction between freeing the memory and calling the destructor in a specific example :-)

I've just edited my post, maybe now it's more clear what I was looking for. I'd like to have a check on my two questions 1) and 2)
Question 1): Is what I wrote above correct?
No, it does not call the constructor and hence all internal variables remain uninitialized. This will be undefined behavior.

Question 2): Can we say that free acts on the pointer variable, while the destructor really acts on the object itself (the vector on the heap)?
free() returns the memory back to the system so that it can be used otherwise.
A destructor is a function that is usually used for cleanup which may be used to free more resources.

In C++ you shouldn't use malloc()/free() because of the initializiing/destroying that might not take place.
Thanks @coder777 for the answer.

No, it does not call the constructor and hence all internal variables remain uninitialized. This will be undefined behavior.

You're right, because malloc doesn't construct, but just allocates memory. Let's assume that I invoke the constructor by using placement new

ptv = new(ptv) std::vector<double>{};

Is now my question 1) (i.e. the analysis of the how and why memory is leaked) right?

Using Valgrind, in the first case it tells I'm leaking 24, while in the second case 16, as expected.
Is now my question 1) (i.e. the analysis of the how and why memory is leaked) right?
What is the question?

Using Valgrind, in the first case it tells I'm leaking 24, while in the second case 16, as expected.
What cases?

What problem are you trying to solve with malloc/free?

I forgott to mention that line 23 is also wrong/undefined behavior because you are calling the destructon on invalid memory. Move line 23 before line 22.
@coder777

I edited my question and my code, I hope that now question 1) is more clear: basically I want to be sure that I understand correctly what happens (in terms of memory leaks) if I call only free and not the destructor, and the other way round.

What cases?


The two cases are:
1. call destructor, but not free.
2. call free, but not destructor
Last edited on
But the question doesn't seem to make any sense:

1. We already said don't use malloc / free in C++ ;
2. You are using malloc on an STL container, which makes even less sense;

Perhaps if the question involved your own original data structure and was in terms of writing your own allocator for it, using carefully new / delete: then it would make more sense to me anyway.
@TheIdeasMan

All I wanted to see is the distinction between delete and free in action. In particular, we know that free doesn't call the destructor, and I wanted to see it with an example by looking
1. call destructor, but not free.
This leaves the object in an invalid state which may lead to undefined behavior.

Do not edit your original post. The discussion based on it makes little sense then.

Are my explanations of those leaks correct?
Since you edited the code the line numbers your refer to are not correct.

But yes: wihout destruct the internal allocated memory by the object will leak. Without freeing the object itself the object memory will leak.
Thanks a lot @coder777 for you patience.

1. call destructor, but not free.
This leaves the object in an invalid state which may lead to undefined behavior.

Yes, because I may write later on that memory location, corrupting my program.


I've one last question: I've seen that if I invoke ONLY the destructor, I don't see the values of my vector when I do cout.

By reading the documentation of std::vector, I believe this is because in the destructor of std::vector they use allocate.destroy(). But I can't figure out what exactly happened to those data after this.
Last edited on
But I can't figure out what exactly happened to those data after this.
It is completely implementation defined. Maybe it sets the pointer to nullptr. It's irrelevant.
Topic archived. No new replies allowed.