Realloc and glocal new/delete operator overriding - c++

Stated that there is no C++ equivalent of the C realloc function, I've found in another question that such a thing is automatically managed by std::vector and we should use it instead.
I'm fine with it. I guess that, since there is no other way of do reallocation, the std::vector will just call realloc for me.
However, the question is: if I'm overriding the new and the delete operators for managing of tracking memory usage globally, they will not be called in the case someone calls old C functions (malloc, calloc, realloc, free).
How can it be done? Is it correct that std::vector replaces realloc?

std::vector won't call realloc; it will use its allocator to achieve something similar: allocating new memory, moving objects into it, then deallocating the old memory. The default allocator uses operator new and operator delete, and so will use your replacements if you provide them.
realloc would be entirely the wrong thing to do if the vector contains non-trivial objects; it copies raw data, while C++ objects generally have to be copied or moved by calling their special functions.
Nothing in the C++ library (except perhaps the default implementations of operator new and operator delete) will call the C allocation functions directly. Since you shouldn't be calling them yourself, you only need to worry about them if you're using a C library.

Related

Why does `make_unique` use `new` while make_shared use `::new`

I am working on a project where a couple of the classes overload operator new and delete to utilize free-lists and I tried to use make_shared to have my allocations managed by smart pointers when I realized that make_shared does not use the overloaded versions but makes an explicit call the global ::new. But according to this make_unique does use the overloaded versions. Which is quite baffling to me. Why does make_shared choose to ignore operator overloading but make_unique doesn't?
make_shared has to allocate two things: the object being constructed and the shared_ptr's control block. To improve performance, it allocates one chunk of memory big enough for both and then placement-news them.
make_unique doesn't need to do that since a unique_ptr doesn't need a control block.
If you want to control how memory is allocated for an object to be managed by a shared_ptr, create an appropriate allocator class and use allocate_shared instead of make_shared.

Malloc vs New for Primitives

I understand the benefits of using new against malloc in C++. But for specific cases such as primitive data types (non array) - int, float etc., is it faster to use malloc than new?
Although, it is always advisable to use new even for primitives, if we are allocating an array so that we can use delete[].
But for non-array allocation, I think there wouldn't be any constructor call for int? Since, new operator allocates memory, checks if it's allocated and then calls the constructor. But just for primitives non-array heap allocation, is it better to use malloc than new?
Please advise.
Never use malloc in C++. Never use new unless you are implementing a low-level memory management primitive.
The recommendation is:
Ask yourself: "do I need dynamic memory allocation?". A lot of times you might not need it - prefer values to pointers and try to use the stack.
If you do need dynamic memory allocation, ask yourself "who will own the allocated memory/object?".
If you only need a single owner (which is very likely), you should
use std::unique_ptr. It is a zero cost abstraction over
new/delete. (A different deallocator can be specified.)
If you need shared ownership, you should use std::shared_ptr. This is not a zero cost abstraction, as it uses atomic operations and an extra "control block" to keep track of all the owners.
If you are dealing with arrays in particular, the Standard Library provides two powerful and safe abstractions that do not require any manual memory management:
std::array<T, N>: a fixed array of N elements of type T.
std::vector<T>: a resizable array of elements of type T.
std::array and std::vector should cover 99% of your "array needs".
One more important thing: the Standard Library provides the std::make_unique and std::make_shared which should always be used to create smart pointer instances. There are a few good reasons:
Shorter - no need to repeat the T (e.g. std::unique_ptr<T>{new T}), no need to use new.
More exception safe. They prevent a potential memory leak caused by the lack of a well-defined order of evaluation in function calls. E.g.
f(std::shared_ptr<int>(new int(42)), g())
Could be evaluated in this order:
new int(42)
g()
...
If g() throws, the int is leaked.
More efficient (in terms of run-time speed). This only applies to std::make_shared - using it instead of std::shared_ptr directly allows the implementation to perform a single allocation both for the object and for the control block.
You can find more information in this question.
It can still be necessary to use malloc and free in C++ when you are interacting with APIs specified using plain C, because it is not guaranteed to be safe to use free to deallocate memory allocated with operator new (which is ultimately what all of the managed memory classes use), nor to use operator delete to deallocate memory allocated with malloc.
A typical example is POSIX getline (not to be confused with std::getline): it takes a pointer to a char * variable; that variable must point to a block of memory allocated with malloc (or it can be NULL, in which case getline will call malloc for you); when you are done calling getline you are expected to call free on that variable.
Similarly, if you are writing a library, it can make sense to use C++ internally but define an extern "C" API for your external callers, because that gives you better binary interface stability and cross-language interoperability. And if you return heap-allocated POD objects to your callers, you might want to let them deallocate those objects with free; they can't necessarily use delete, and making them call YourLibraryFree when there are no destructor-type operations needed is unergonomic.
It can also still be necessary to use malloc when implementing resizable container objects, because there is no equivalent of realloc for operator new.
But as the other answers say, when you don't have this kind of interface constraint tying your hands, use one of the managed memory classes instead.
It's always better to use new. If you use malloc you still have to check manually if space is allocated.
In modern c++ you can use smart pointers. With make_unique and make_shared you never call new explicitly. std::unique_ptr is not bigger than the underlying pointer and the overhead of using it is minimal.
The answer to "should I use new or malloc" is single responsibillity rule.
Resource management should be done by a type that has that as its sole purpose.
Those classes already exists, such as unique_ptr, vector etc.
Directly using either malloc or new is a cardinal sin.
zwol's answer already gives the correct correctness answer: Use malloc()/free() when interacting with C interfaces only.
I'm not going to repeat those details, I'm going to answer the performance question.
The truth is, that the performance of malloc() and new can, and does differ. When you perform an allocation with new, the memory will generally be allocated via call to the global operator new() function, which is distinct from malloc(). It is trivial to implement operator new() by calling through to malloc(), but this is not necessarily done.
As a matter of fact, I've seen a system where an operator new() that calls through to malloc() would outperform the standard implementation of operator new() by roughly 100 CPU cycles per call. That's definitely a measurable difference, and a clear indication that the standard implementation does something very different from malloc().
So, if you are worried about performance, there is three things to do:
Measure your performance.
Write replacement implementations for the global operator new() function and its friends.
Measure your performance and compare.
The gains/losses may or may not be significant.

What/how does C++ delete operator work

When we call delete on a pointer it calls the destructor of the object, but after the destructor it frees the memory the object was pointing to. If we overwrite the delete operator in a class, how would we do the same thing the original delete operator does with actually freeing the memory?
I'm thinking in terms of garbage collecting and smart pointers. Is it possible to have the default delete functionality of actually freeing the memory somehow (copy/paste the default delete operator code) if we overwrite a classes delete operator?
Yes, I'm just playing around with bastardizing C++. This isn't really for anything specific. Just trying to understand the possibilities around this.
I hate templated smart pointers and would love to try and implement smart pointers that allow you to still use the normal delete operator and no templated classes to wrap the pointer into.
How the delete operator frees memory depends on how the
corresponding new operator acquired it. If you're implementing
class specific operators, you probably need to implement both
(or neither). In this case, you can use ::operator new to get
the memory, and ::operator delete to free it.
If you're thinking of replacing the global operator new and
operator delete, you can use malloc or free to allocate.
Formally, these are the only functions guaranteed not to use
new and delete themselves (but it's a good bet that
functions like memset don't either).
If you're interested in garbage collection, of course, operator
new will allocate from the garbage collected arena, and
operator delete will be a no-op. (I've done this using the
Boehm collector, and it works quite well.) You can do this on
a class by class basis, or you can do it globally. If you do
this, you do not have to delete except if your program logic
requires it. But be aware that the garbage collector will not
call your destructor. If the destructor is trivial, or is only
used for memory management (and thus has been subsumed by the
garbage collector), this is fine, and this is often the case.
One thing that you cannot change is that the new operator will
call a constructor (assuming the type has a non-trivial one),
after having called operator new, and the delete operator
will call the destructor, before calling operator delete.

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

What is the use of malloc and free when we have new and delete in C++. I guess function of both free and delete is same.
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.
In C++, it is rarely useful that one would use malloc & free instead of new& delete.
One Scenario I can think of is:
If you do not want to get your memory initialized by implicit constructor calls, and just need an assured memory allocation for placement new then it is perfectly fine to use malloc and free instead of new and delete.
On the other hand, it is important to know that mallocand new are not same!
Two important differences straight up are:
new guarantees callng of constructors of your class for initializing the class members while mallocdoes not, One would have to do an additional memset or related function calls post an malloc to initialize the allocated memory to do something meaningful.
A big advantage is that for new you do not need to check for NULL after every allocation, just enclosing exception handlers will do the job saving you redundant error checking unlike malloc.
First, when you speak of new and delete, I assume you mean the
expressions, and not the operator new and operator delete functions.
The new and delete expressions are not related to malloc and
free, and only manage memory incidentally; their main role is to
manage object lifetime: a new expression will call the operator new
function to obtain memory, and then call the constructor; a delete
expression will call the destructor before calling operator delete to
free the memory. For the most part, objects should be created, and
not simply allocated, which means using the expressions exclusively.
There are some rare cases where one wants to separate allocation and
initialization (creation); implementing things like std::vector is a
classical example, where you'll allocate for many objects in one go, but
only construct one at a time. In such cases, you'll use the operator
new function for allocation, and placement new for initialization; at
the other end, you'll explicitly call the constructor (something like
p->~T()) for destruction, and use the operator delete function to
free the memory.
Off hand, I can only think of two cases where you'd use malloc and
free in C++. The first is to implement your own replacements of the
::operator new and ::operator delete functions. (I often replace
the global ::operator new and ::operator delete with debugging
versions, which trace allocations, put guard zones around the allocated
memory, etc.) The other is when interacting with a legacy library
written in C: if the library says to pass a pointer to memory allocated
by malloc (because it will free it itself using free), or more
commonly, returns a pointer to memory allocated by malloc, which
you're expected to free, then you must use malloc and free. (The
better libraries will provide their own allocation and deallocation
functions, which do more or less what the new and delete operators
do, but there will always be things like strdup().)

new vs. new (featuring malloc!)

In C++, it's standard to always use new over malloc(). However, in this question, the most portable way of overloading the new operator while avoiding platform specific code is to place a call to malloc() within it to do the actual allocation.
When overloaded, constructors are called and type-safety is kept. In addition, you can monitor and control how memory is allocated.
My question, when used in this capacity, are there still any downsides to using malloc() within C++?
If you wish to override new and delete then you pretty much have to use malloc and free. That's how it is meant to be done. Do not be afraid.
The downsides of using malloc() outside of the implementation of new() remain.
The biggest downside I can think off is you can't explicitly call delete or delete [] on a pointer that has been allocated using malloc() without invoking undefined behavior. If you are going to go the highly un-recommended path and use malloc() to allocate memory explicitly for C++ objects, then you are still going to have to call placement new in order to properly call a constructor to initialize the memory location allocated by malloc(). Without an operator new wrapper on malloc(), you'll also have to test to make sure you do not get a NULL return value, and create some code to handle cases where you do without the benefit of throwing an exception. It's also very dangerous, and can incur a number of undefined behaviors, if you simply tried to use C-library functions like memcpy() to copy C++ objects into heap memory allocated with malloc().
Furthermore, because you utilized placement new for your object construction, you are going to have to explicitly call the destructuors for your dynamically allocated objects, and then explicitly call free() on the pointers. This again can cause all sorts of problems if it's not handled correctly, especially if you wanted to work with polymorphic types and virtual base-classes.
If you are going to work with just malloc() and free(), a nice rule of thumb to avoid undefined behavior pitfalls is to keep the objects you allocate and deallocate with malloc() and free() to POD-types. That means non-polymorphic structs or classes with no user-defined constructors, destructors, copy-constructors, assignment operators, private/protected non-static data-members, or base-classes, and all the non-static data-members of the struct/class are POD-types themselves. Since POD-types are basically C-style structs (but with the added ability to define non-static methods and a this pointer), you can safely do C-style memory management with them.
You stated it yourself... the downside to using malloc/free directly in C++ code is that constructors and destructors will not be run; using new/delete ensures that constructors and destructors are run. However, there is nothing wrong with indirectly using malloc via the new/delete operators.