New, Delete ,Malloc & Free

What is the difference between new/delete and malloc/free?

new / delete

  • Allocate / release memory
    1. Memory allocated from 'Free Store'.
    2. Returns a fully typed pointer.
    3. new (standard version) never returns a NULL (will throw on failure).
    4. Are called with Type-ID (compiler calculates the size).
    5. Has a version explicitly to handle arrays.
    6. Reallocating (to get more space) not handled intuitively (because of copy constructor).
    7. Whether they call malloc / free is implementation defined.
    8. Can add a new memory allocator to deal with low memory (std::set_new_handler).
    9. operator new / operator delete can be overridden legally.
    10. Constructor / destructor used to initialize / destroy the object.

malloc / free

  • Allocate / release memory
    1. Memory allocated from 'Heap'.
    2. Returns a void*.
    3. Returns NULL on failure.
    4. Must specify the size required in bytes.
    5. Allocating array requires manual calculation of space.
    6. Reallocating larger chunk of memory simple (no copy constructor to worry about).
    7. They will NOT call new / delete.
    8. No way to splice user code into the allocation sequence to help with low memory.
    9. malloc / free can NOT be overridden legally.

Table comparison of the features:






























































Featurenew / deletemalloc / free
Memory allocated from'Free Store''Heap'
ReturnsFully typed pointervoid*
On failureThrows (never returns NULL)Returns NULL
Required sizeCalculated by compilerMust be specified in bytes
Handling arraysHas an explicit versionRequires manual calculations
ReallocatingNot handled intuitivelySimple (no copy constructor)
Call of reverseImplementation definedNo
Low memory casesCan add a new memory allocatorNot handled by user code
OverridableYesNo
Use of constructor / destructorYesNo

Why use malloc/free, when we have new/delete?

They're not the same. new calls the constructor, malloc just allocates the memory.

Also, it's undefined behavior mixing the two (i.e. using new with free and malloc with delete).

In C++, you're supposed to use new and delete, malloc and free are there for compatibility reasons with C.

malloc/free and new/delete compatibility in C++?

Yes, you can interleave them - just use a deallocation function matching the one used for allocation. The problem only arises if you use a wrong deallocation function.

Note that it's not that easy when you have several libraries - those might use different heaps and so even though you use a right named function it might happen to be implemented in the wrong module and so use the wrong heap which will drive you right into undefined behavior. See this answer for a better idea of what I'm talking about here.

Why are new()/delete() slower than malloc()/free()?

Look at this piece of C code:

struct data* pd = malloc(sizeof(struct data));
init_data(pd);

The new operator in C++ is essentially doing what the above piece of code does. That's why it is slower than malloc().

Likewise with delete. It's doing the equivalent of this:

deinit_data(pd);
free(pd);

If the constructors and destructors are empty (like for built-ins), new and delete shouldn't be slower than malloc() and free() are. (If they are, it's often due to the fact that common implementations call malloc()/free() under the hood, so they are a wrapper around them. Wrapping costs. Also, there might be code that needs to find out that no constructors/destructors are to be called. That would cost, too.)

Edit To answer your additional question:

new and delete aren't functions, they are operators. This: new data() is called a new expression. It does two things. First it calls the operator new, then it initializes the object, usually by invoking the appropriate constructor. (I say "usually" because built-ins don't have constructors. But a new expression involving a built-in works the same nevertheless.)

You can manipulate both of these phases. You can create your own constructors to manipulate initialization of your types and you can overload operator new (even with several overloads having different additional arguments and also specifically for each class, if you want) in order to manipulate allocation of free storage. If you don't implement your own operator new, the version from the standard library is used. A common implementation of this calls malloc().

Likewise, if you write delete pd, called a delete expression, two things happen: depending on pd, the object is de-initialized, usually by calling its destructor, then the memory is released by calling the appropriate operator delete.

Again, you can manipulate both phase, by writing your own destructor, and by writing your own version of operator delete. (The version of operator delete that comes with your standard library is often implemented to call free().)

malloc and free vs new and delete

new calls a constructor, malloc() does not. delete calls a destructor, free() does not. If the class in question allocates memory internally, then yes, you are likely to encounter a memory leak.

If you have to use malloc() and free() (and in C++, you really shouldn't be), you will have to use placement new to call the constructor, and call the destructor yourself, eg:

pStr = static_cast<String*>(malloc(4 * sizeof(String)));
if (pStr)
{
for (int i = 0; i < 4; ++i)
new (&pStr[i]) String;
...
for (int i = 3; i >= 0; --i)
pStr[i].~String();
free(pStr);
}

And if you really need to mimic new[], you should handle exceptions thrown by constructors, eg:

pStr = static_cast<String*>(malloc(4 * sizeof(String)));
if (!pStr)
throw std::bad_alloc("");

int numConstructed = 0;
try
{
for (int i = 0; i < 4; ++i)
{
new (&pStr[i]) String;
++numConstructed;
}
}
catch (const std::exception &)
{
for (int i = numConstructed-1; i >= 0; ++i)
pStr[i]).~String();
throw;
}

...

for (int i = numConstructed-1; i >= 0; --i)
pStr[i].~String();
free(pStr);

Any possible use of free() with new & delete with malloc()?

  1. For one thing, they may be using completely different heaps. In more than one application of ours the global new and delete are redefined to perform some additional bookkeeping; if you pass to free a pointer returned by new it won't be recognized as stuff from malloc, because we are keeping extra info at the start of each memory block. The standard library can do the same.
  2. Why should there be? As already said, the memory they return can come from different heaps, so it makes no sense to use one to deallocate stuff from the other. Now, if you are allocating POD types and if the global new operator is just a thin wrapper around malloc, in theory it could accidentally work to use freefor memory allocated with new, but I really don't see the point in doing so besides adding confusion (and potential undefined behavior).
  3. new and delete were introduced as operators to deal with non-POD types. If all you want is "raw" memory malloc (or, in general, a single function) is fine, but if you want to allocate objects stuff gets more complicated; the allocation mechanism must be aware of the type of the allocated data, not just of the required size, because it has to invoke the constructors (the same for delete, which has to invoke destructors, although new could have just saved the function pointer to the destructor).

What if, memory allocated using malloc is deleted using delete rather than free

When you call delete a pointer, the compiler will call the dtor of the class for you automatically, but free won't. (Also new will call ctor of the class, malloc won't.)

In you example, a char array apparently don't have a dtor, so delete does nothing but return the memory. That's why it's okay. (Or vise versa, new a char array and then free it.)

But there can still be a problem: what if new and malloc are borrowing memory from different heap manager?

Imagine that, you borrow money from people A, and return to people B later. Even if you are okay with that, have you ever consider A's feeling?

BTW, you should use delete [] pArray; to free an array allocated using new[].

Replace malloc and free by new and delete in a memory pool

Your code is broken and you need to fix it first.

Pre-C++11:

Unions cannot contain a non-static data member with a non-trivial special member function (copy constructor, copy-assignment operator, or destructor).

Post-C++11:

If a union contains a non-static data member with a non-trivial special member function (default constructor, copy/move constructor, copy/move assignment, or destructor), that function is deleted by default in the union and needs to be defined explicitly by the programmer.

See here. You follow neither rule. You need to fix this.

Once you fix it, you can just use node = new MemoryPoolNode() and delete node;.

For C++11, this will do:

union MemoryPoolNode
{
MemoryPoolNode *next;
T data;

MemoryPoolNode() : next(NULL) { ; }
~MemoryPoolNode() { ; }
};

new, delete ,malloc & free

If you do so you will run into undefined behavior. Never try that. Although new might be implemented through malloc() and delete might be implemented through free() there's no guarantee that they are really implemented that way and also the user can overload new and delete at his discretion. You risk running into heap corruption.

Other than that don't forget that when you call malloc() you get raw memory - no constructor is invoked - and when you call free() no destructor is invoked. This can as well lead to undefined behavior and improper functioning of the program.

The bottom line is... never do this.



Related Topics



Leave a reply



Submit