Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why should I prefer using the free store over the heap?

In Exceptional C++, Herb Sutter wrote in Item 35 as a guideline:

Prefer using the free store (new/delete). Avoid using the heap (malloc/free).

Why should I?

If an implementation chooses to implement new by using malloc, an overhead would probably incur, so that looks like a bad piece of advice as far as performance is concerned.

like image 574
qdii Avatar asked Dec 20 '22 06:12

qdii


1 Answers

The new and delete keywords in C++ usually are implemented in terms of malloc and free, but they're designed to do different things.

In C++, if you say

new T(/* args */)

C++ will do the following:

  • Attempt to allocate enough memory to hold an object of type T.
  • On failure, attempt to use the new handler to free space, eventually throwing a std::bad_alloc object if no memory is available.
  • Attempt construct an object of type T in that block of memory.
  • Automatically deallocate the memory if the construction of the object of type T throws an exception.

If you just use malloc, you have to do all of these steps manually, which would be very, very hard. It might look something like this:

T* memory = nullptr;
while (true) {
   memory = static_cast<T*>(malloc(sizeof(T)));
   if (memory != nullptr) break;

   std::get_new_handler()();  
}

try {
    new (memory) T(/* args */);
} catch (...) {
    free(memory);
    throw;
}

There are some other nuances here that I've glossed over (like calling operator new instead of malloc, or handling zero-sized requests, etc.), but I hope this helps explain how new and malloc are different.

So why should you use new over malloc? Well, there's a few reasons:

  • It's much safer. With malloc you can forget to check the return type for a null pointer, or you could request the wrong amount of storage space, or you could forget to call the constructor on the object, or you could forget to deallocate memory if the constructor throws an exception, etc.

  • It's more type-safe. malloc returns a void*, which is just a pointer to a block of memory. Using malloc, you have to cast the pointer to the proper type, which introduces the potential for errors later on.

  • It allows customization. Certain types overload operator new to request memory in an unusual way, such as from a pooled allocator or from certain pieces of memory that might be faster, or using a custom allocator that optimizes over the usage pattern. Given this, you can automatically customize all times where memory is allocated dynamically for an object of type T simply by defining operator new and operator delete. If you use malloc, you have to chase down all memory allocation sites throughout the entire program.

That said, there are some advantages to malloc. If you know for certain that you're allocating objects that are trivial objects (like primitives or structs that just hold data), it might be slightly faster to use malloc. malloc also lets you use realloc, which free doesn't. But honestly, you're probably better off just using std::vector or std::array in cases like this, since they're safer, easier to debug, and with good compiler support are likely to be aggressively optimized.

Hope this helps!

like image 158
templatetypedef Avatar answered Dec 24 '22 00:12

templatetypedef