logo

C / C++ - Memory Management

C++: new / delete

Use keywords new and delete, or smart pointers.

Read more: Smart Pointers

char *pBuffer = new char[1024];
delete[] pBuffer;

new vs malloc

Takeaways:

  • You cannot mix new / free and malloc / delete.
  • in C++, don't use malloc for C++ without a really good reason

new is more type-safe; malloc is not typesafe in any meaningful way. In C++ you are required to cast the return from void*.

Foo *f1 = malloc(1); // error, no cast
Foo *f2 = static_cast<Foo*>(malloc(sizeof(Foo)));

malloc returns NULL if allocation fails. new will throw std::bad_alloc.

int* p_scalar = new int(5);  // Does not create 5 elements, but initializes to 5
int* p_array  = new int[5];  // Creates 5 elements

Use malloc if you need to change the size of your buffer of data. realloc can be used to extend the size of a chunk of memory.

C: malloc() / calloc() / free()

Use functions malloc() / calloc() and free().

malloc()

malloc() = memory allocation

It returns a pointer of type void which can be cast into a pointer of any form. It doesn’t iniatialize memory at execution time so that it has initializes each block with the default garbage value initially.

Example:

ptr = (int*) malloc(100 * sizeof(int));

calloc()

calloc() = contiguous allocation, allocate the specified number of blocks of memory of the specified type.

void *calloc(size_t nitems, size_t size)

Example:

int* a = (int*) calloc(5, sizeof(int));

calloc() vs malloc()

  • malloc() does not set the memory to zero, calloc() sets allocated memory to zero.
  • malloc() has one parameter, calloc() has two.

realloc()

ptr = realloc(ptr, newSize);

The function returns a void pointer to this memory location, which can then be cast to the desired type.

free()

Free the memory when it is no longer used.

Placement new

In C++, placement new is a version of the new operator that allows constructing an object at a specific, pre-allocated memory location. It separates memory allocation from object construction, offering control over where objects are created. Unlike the regular new operator, which allocates memory and then constructs the object, placement new only handles the construction part.

Placement new takes the form new (address) Type(arguments). Here, address is a pointer to the pre-allocated memory, Type is the class of the object to be constructed, and arguments are any constructor arguments. The operator returns a pointer to the constructed object at the specified address.

It's important to note that since placement new doesn't allocate memory, it's the programmer's responsibility to manage the memory lifecycle. This includes ensuring that the memory is properly allocated and deallocated, and that the object's destructor is called when it's no longer needed. Failure to do so can lead to memory leaks or other issues.

// Allocate memory
alignas(MyClass) char buffer[sizeof(MyClass)]; // Ensure proper alignment

// Use placement new to construct the object in the allocated memory
MyClass* obj = new (buffer) MyClass(10);

// Use the object
obj->printValue();

// Destroy the object (manually call the destructor)
obj->~MyClass();