Malloc() VS. Heapalloc()

malloc() vs. HeapAlloc()

You are right that they both allocate memory from a heap. But there are differences:

  • malloc() is portable, part of the standard.
  • HeapAlloc() is not portable, it's a Windows API function.

It's quite possible that, on Windows, malloc would be implemented on top of HeapAlloc. I would expect malloc to be faster than HeapAlloc.

HeapAlloc has more flexibility than malloc. In particular it allows you to specify which heap you wish to allocate from. This caters for multiple heaps per process.

For almost all coding scenarios you would use malloc rather than HeapAlloc. Although since you tagged your question C++, I would expect you to be using new!

Is there a fundamental difference between malloc and HeapAlloc (aside from the portability)?

As I found out the hard way...

The difference isn't fundamental, but HeapReAlloc (which uses RtlReAllocateHeap) does not automatically treat a null pointer as a hint to call HeapAlloc; it fails instead.

What's the differences between VirtualAlloc and HeapAlloc?

Each API is for different uses. Each one also requires that you use the correct deallocation/freeing function when you're done with the memory.

VirtualAlloc

A low-level, Windows API that provides lots of options, but is mainly useful for people in fairly specific situations. Can only allocate memory in (edit: not 4KB) larger chunks. There are situations where you need it, but you'll know when you're in one of these situations. One of the most common is if you have to share memory directly with another process. Don't use it for general-purpose memory allocation. Use VirtualFree to deallocate.

HeapAlloc

Allocates whatever size of memory you ask for, not in big chunks than VirtualAlloc. HeapAlloc knows when it needs to call VirtualAlloc and does so for you automatically. Like malloc, but is Windows-only, and provides a couple more options. Suitable for allocating general chunks of memory. Some Windows APIs may require that you use this to allocate memory that you pass to them, or use its companion HeapFree to free memory that they return to you.

malloc

The C way of allocating memory. Prefer this if you are writing in C rather than C++, and you want your code to work on e.g. Unix computers too, or someone specifically says that you need to use it. Doesn't initialise the memory. Suitable for allocating general chunks of memory, like HeapAlloc. A simple API. Use free to deallocate. Visual C++'s malloc calls HeapAlloc.

new

The C++ way of allocating memory. Prefer this if you are writing in C++. It puts an object or objects into the allocated memory, too. Use delete to deallocate (or delete[] for arrays). Visual studio's new calls HeapAlloc, and then maybe initialises the objects, depending on how you call it.

In recent C++ standards (C++11 and above), if you have to manually use delete, you're doing it wrong and should use a smart pointer like unique_ptr instead. From C++14 onwards, the same can be said of new (replaced with functions such as make_unique()).


There are also a couple of other similar functions like SysAllocString that you may be told you have to use in specific circumstances.

Visual Studio 2010 C++: malloc()/HeapAlloc always allocates new page for even smallest alloc size

Windows includes a feature called "Page Heap" which is helpful in locating memory corruption defects. It operates by placing each allocation on a page, which causes the processor to issue an access violation if the program corrupts memory instead of entering undefined behavior territory.

Sounds like somewhere in your big application someone has turned on page heap, or you have triggered some kind of application compatibility setting in Windows in your big application that enabled Page Heap.

Note that this is a Windows setting (HeapAlloc is a Win32 API), not a debug/release compiler setting.

LocalAlloc Vs GlobalAlloc Vs malloc Vs new

Excerpts from Raymond Chen's OldNewThing

Back in the days of 16-bit Windows, the difference was significant.

In 16-bit Windows, memory was accessed through values called
“selectors”, each of which could address up to 64K. There was a
default selector called the “data selector”; operations on so-called
“near pointers” were performed relative to the data selector. For
example, if you had a near pointer p whose value was 0x1234 and your
data selector was 0x012F, then when you wrote *p, you were accessing
the memory at 012F:1234. (When you declared a pointer, it was near by
default. You had to say FAR explicitly if you wanted a far pointer.)

Important: Near pointers are always relative to a selector, usually
the data selector.

The GlobalAlloc function allocated a selector that could be used to
access the amount of memory you requested. You could access the memory
in that selector with a “far pointer”. A “far pointer” is a selector
combined with a near pointer. (Remember that a near pointer is
relative to a selector; when you combine the near pointer with an
appropriate selector, you get a far pointer.)

Every instance of a program and DLL got its own data selector, known
as the HINSTANCE. Therefore, if you had a near pointer p and accessed
it via *p from a program executable, it accessed memory relative to
the program instance’s HINSTANCE. If you accessed it from a DLL, you
got memory relative to your DLL’s HINSTANCE.

Therefore, that in 16-bit Windows, the LocalAlloc and GlobalAlloc
functions were completely different! LocalAlloc returned a near
pointer, whereas GlobalAlloc returned a selector.

Pointers that you intended to pass between modules had to be in the
form of “far pointers” because each module has a different default
selector. If you wanted to transfer ownership of memory to another
module, you had to use GlobalAlloc since that permitted the recipient
to call GlobalFree to free it.

Even in Win32, you have to be careful not to confuse the local heap
from the global heap. Memory allocated from one cannot be freed on the
other. All the weirdness about near and far pointers disappeared with
the transition to Win32. But the local heap functions and the global
heap functions are nevertheless two distinct heap interfaces.

Also, the link specified by you clearly says that,

Starting with 32-bit Windows, GlobalAlloc and LocalAlloc are
implemented as wrapper functions that call HeapAlloc using a handle to
the process's default heap, and HeapAlloc can be instructed to raise
an exception if memory could not be allocated, a capability not
available with LocalAlloc.

For your confusion on malloc vs new, Billy ONeal's answer summarizes that pretty clearly.

For the difference between malloc and HeapAlloc,
David Heffernan's and Luis Miguel Huapaya's answer combined gives the perfect solution::

  • malloc is portable, part of the standard. malloc (and other C runtime heap functions) are module dependant, which means that if you call malloc in code from one module (i.e. a DLL), then you should call free within code of the same module or you could suffer some pretty bad heap corruption.
  • HeapAlloc is not portable, it's a Windows API function. Using HeapAlloc with GetProcessHeap instead of malloc, including overloading new and delete operators to make use of such, allow you to pass dynamically allocated objects between modules and not have to worry about memory corruption if memory is allocated in code of one module and freed in code of another module once the pointer to a block of memory has been passed across to an external module.

On Memory Allocation and C++

a) In this case I think they're eliding "run-time library" to "run-time". In other words it depends on the implementation in your C library.

b) Indeed new is C++ specific. HeapAlloc, etc are technically usable in C and C++.

c) They can't be used to create C++ objects because they won't call constructors so the point is pretty moot. In C++ you should use new and delete.

Memory allocation on Windows C code

Stick with malloc unless you have a compelling reason to use something different. It will be implemented underneath in terms of the OS memory allocation primitives, but there is no real advantage in diving down to that layer yourself.

A few API calls I believe need a memory block allocated from a Windows heap, but you will know when you come across them.

Or if you want to do something more advanced, like use shared memory, or need to control the permissions on the memory pages directly then you will need to look at the Windows API calls like VirtualAlloc.



Related Topics



Leave a reply



Submit