Difference Between Global Non-Throwing ::Operator New and Std::Malloc

Difference between global non-throwing ::operator new and std::malloc

The main differences, aside from syntax and free vs. delete, are

  1. you can portably replace ::operator new;
  2. malloc comes with realloc, for which new has no equivalent;
  3. new has the concept of a new_handler, for which there is no malloc equivalent.

(Replacing malloc opens up a can of worms. It can be done, but not portably, because it requires knowledge of the linker.)

Regarding the differences between malloc and new in terms of their respective mechanisms of handling memory allocation?

  • malloc doesn't throw bad_alloc exception as new does.

    • Because malloc doesn't throw exceptions, you have to check its result against NULL (or nullptr in c++11 and above), which isn't necessary with new. However, new can be used in a way it won't throw expections, as when function set_new_handler is set
  • malloc and free do not call object constructors and destructors, since there is no objects in C.
  • see this question and this post.

Why does replacing malloc() require knowledge of the linker but ::operator new() does not?

Standard C++ makes provisions for overriding ::operator new. While the implementation is certainly messy and linker-related, a C++ program can just define a different ::operator new and it works. The C++ standard explicitly says: Programs can replace these with their own definitions (etc. etc. various restrictions and details).

malloc on the other hand is an ordinary function defined in an ordinary library, and C (and C++, for that matter) has no facilities for replacing a function like that. You can convince virtually every linker under the sun to link to your libc sans malloc and resolve references to malloc to some code from another library/object file. But you can't just define a different malloc functions since that violates the one-definition rule: You end up with two functions called "malloc" in the program, which is both prohibited by the standard (for non-static, non-anonymous-namespace, non-inline, ... functions) and a serious problem for linkers (most likely, an error or one of the two definitions is dropped).

Difference between 'new operator' and 'operator new'?

I usually try to phrase things differently to differentiate between the two a bit better, but it's a good question in any case.

Operator new is a function that allocates raw memory -- at least conceptually, it's not much different from malloc(). Though it's fairly unusual unless you're writing something like your own container, you can call operator new directly, like:

char *x = static_cast<char *>(operator new(100));

It's also possible to overload operator new either globally, or for a specific class. IIRC, the signature is:

void *operator new(size_t);

Of course, if you overload an operator new (either global or for a class), you'll also want/need to overload the matching operator delete as well. For what it's worth, there's also a separate operator new[] that's used to allocate memory for arrays -- but you're almost certainly better off ignoring that whole mess completely.

The new operator is what you normally use to create an object from the free store:

my_class *x = new my_class(0);

The difference between the two is that operator new just allocates raw memory, nothing else. The new operator starts by using operator new to allocate memory, but then it invokes the constructor for the right type of object, so the result is a real live object created in that memory. If that object contains any other objects (either embedded or as base classes) those constructors as invoked as well.

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

Malloc vs New for Primitives

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:

    1. new int(42)
    2. g()
    3. ...

    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.



Related Topics



Leave a reply



Submit