68

What is the difference between malloc() and HeapAlloc()? As far as I understand malloc allocates memory from the heap, just as HeapAlloc, right?

So what is the difference?

genpfault
  • 51,148
  • 11
  • 85
  • 139
TCS
  • 5,790
  • 5
  • 54
  • 86

8 Answers8

95

Actually, 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 (and this has been well documented). 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.

  • 18
    Finally, this is the most important answer here. `malloc()` is portable but when you need to move objects and DLLs get involved, you need the Heap. For Windows developers, I suggest using the Heap and writing a custom STL allocator for the Heap too. – CodeAngry Nov 21 '12 at 11:26
  • Is the objection still valid? For example VC 2013 CRT initializes the _crtheap as GetProcessHeap(), so malloc/free from different DLLs should already use the same GetProcessHeap(). There is a different story if mixing 'release' and 'debug' CRTs. The later adds an offset to the returned pointer, so indeed allocating by the debug-versions and freeing by the release-version (or reverse) will crash the program. – isti_spl Jun 15 '16 at 07:46
  • 9
    Would love a link to the "well documented" that you mention. – the_endian Mar 09 '17 at 05:20
59

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!

genpfault
  • 51,148
  • 11
  • 85
  • 139
David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • 39
    How could `malloc` be faster than `HeapAlloc` if it's implemented on top of `HeapAlloc`? – dan04 Nov 22 '11 at 09:19
  • 13
    @dan04 Because `malloc` may implement further sub allocation patterns. – David Heffernan Nov 22 '11 at 09:20
  • 2
    Correct. Serves no other purpose than being a trap for an inexperienced developer. The usual "We Do The Same But Giving It An Other Name To Introduce Some Incompatibilities" thingy from MS – Gunther Piez Nov 22 '11 at 09:20
  • 9
    @drhirsch: "trap for inexperienced developers" sure; "serves no other purpose," not so much. You can use it with per thread heaps or allocate memory from a heap which is executable. – user7116 Nov 22 '11 at 09:23
  • 1
    I stand corrected, it has some other purpose I didn't know of. But somebody asking "malloc or HeapAlloc" does obviously not need thread local storage (which is missing in the C standard library) or executable memory – Gunther Piez Nov 22 '11 at 10:28
  • 3
    `malloc` doesn't need to do suballocations (since Win2000 SP4); the OS-provided Low Fragment Heap (LFH) can now make small allocations efficiently as well. – MSalters Nov 22 '11 at 10:40
  • 9
    it has some other purpose, like being used in languages other than C or C++. There are actually more programmers than those who use C or C++. – Sheng Jiang 蒋晟 Nov 22 '11 at 14:42
  • 31
    @drhirsh: what MS is doing here is no different than what happens on other platforms; malloc() is rarely (ever?) supplied directly by the OS, but instead the C library implements it in terms of an underlying OS primitive. On Win32, it's HeapAlloc(); on unix, malloc() is typically implemented in terms of either sbrk() or mmap(). A similar situation exists with files: C's fopen() is implemented in terms of CreateFile() on Win32, or open() on unix. The OP's qu here is really analogous to "fopen() vs open()" or "fopen() vs CreateFile()". – BrendanMcK Nov 22 '11 at 20:15
  • If you were in the act of building your own compiler/language then the OS provided memory management method (ie heapalloc) is more portable. Else you would be tied to the portability of the C runtime. This is likely what most C compilers do anyways, but in today's age where there are multiple OS out there it's unlikely one C compiler (at least an open source one) will cover many OS beyond the top several in use. –  Aug 07 '12 at 17:52
  • 1
    @BrendanMcK : you are right otherwise but incorrect with the analogy on `fopen`. `fopen` does nothing more than a platform independent-ization of a call. it is a direct wrap. But malloc can be like David says. Take a look at `dlmalloc` implementation; the whole purpose is to reduce calls to `srbk` as much as possible, by using custom bin packing, pools up to 256k and ordered free lists. From what I gather, microsoft is trying to give all of these features directly in `HeapAlloc`, effectively removing any need for a clever `malloc`. From personal benchmarks, Win8 scheme is now really fast – v.oddou Jul 08 '15 at 03:35
30

With Visual C++, the function malloc() or the operator new eventually calls HeapAlloc(). If you debug the code, you will find the function _heap_alloc_base() (in the file malloc.c) is calling return HeapAlloc(_crtheap, 0, size) where _crtheap is a global heap created with HeapCreate().

The function HeapAlloc() does a good job to minimize the memory overhead, with a minimum of 8 bytes overhead per allocation. The largest I have seen is 15 bytes per allocation, for allocations ranging from 1 byte to 100,000 bytes. Larger blocks have larger overhead, however as a percent of the total allocated it remains less than 2.5% of the payload.

I cannot comment on performance because I have not benchmarked the HeapAlloc() with a custom made routine, however as far as the memory overhead of using HeapAlloc() is concerned, the overhead is amazingly low.

Tom Lee
  • 360
  • 1
  • 3
  • 10
Daniel Morin
  • 301
  • 3
  • 2
  • 3
    and HeapAlloc() calls RtlHeapAlloc() implemented in ntdll.dll, kernel32.dll, kernalebase.dll – Phiber Mar 27 '14 at 18:56
  • I have a benchmark in my open address hash map http://sourceforge.net/projects/cgenericopenaddresshashmap/ that suggests that Windows 8 malloc is at least 5 times faster than Windows 7. Somebody suggested [here](http://www.gamedev.net/topic/669459-massive-allocation-perf-difference-between-win8-win7-and-linux/) that MS CRT malloc does nothing more than wrap `HeapAlloc`, do you confirm ? – v.oddou Jul 08 '15 at 03:28
7

malloc is a function in the C standard library (and also in the C++ standard library).

HeapAlloc is a Windows API function.

The latter lets you specify the heap to allocate from, which I imagine can be useful for avoiding serialization of allocation requests in different threads (note the HEAP_NO_SERIALIZE flag).

halfer
  • 19,824
  • 17
  • 99
  • 186
Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
3

In systems where multiple DLLs may come and go (via LoadLibrary/Freelibrary), and when memory may be allocated within one DLL, but freed in another (see previous answer), HeapAlloc and related functions seem to be the least-common-denominator for successful memory sharing.

Thread safe, presumably highly optimized by PhDs galore, HeapAlloc appears to work in all kinds of situations where our not-so-shareable code using malloc/free would fail.

We are a C++ embedded shop, so we have overloaded operator new/delete across our system to use the HeapAlloc( GetProcessHeap( ) ) which can stubbed (on target) or native (to windows) for code portability.

So far no problems now that we have bypassed malloc/free which seem indisputably DLL specifically, a new "heap" for each DLL load.

1

Additionally, you can refer to:

https://msdn.microsoft.com/en-us/library/windows/desktop/aa366705(v=vs.85).aspx

Which stands that you can enable some features of the HEAP managed by WinApi memory allocator, eg "HeapEnableTerminationOnCorruption".

As I understand, it makes some basic heap overflow protections which may be considered as an added value to your application in terms of security.

(eg, I would prefer to crash my app (as an app owner) rather than execute arbitrary code)

Other thing is that it might be useful in early phase of development, so you could catch memory issues before going to the production.

anonymous
  • 11
  • 1
-1

malloc is exported function by C run-time library(CRT) which is compiler specific.
C run-time library dll name changes from visual studio versions to versions.

HeapAlloc function is exported by kernel32.dll present in windows folder.

rpk
  • 70
  • 9
-2

This is what MS has to say about it: http://msdn.microsoft.com/en-us/library/windows/desktop/aa366533(v=vs.85).aspx

One thing one one mentioned thus far is: "The malloc function has the disadvantage of being run-time dependent. The new operator has the disadvantage of being compiler dependent and language dependent."

Also, "HeapAlloc can be instructed to raise an exception if memory could not be allocated"

So if you want your program to run with any CRT, or perhaps no CRT at all, you'd use HeapAlloc. Perhaps only people who would do such thing would be malware writers. Another use might be if you are writing a very memory intensive application with specific memory allocation/usage patterns that you'd rather write your own heap allocator instead of using a CRT one.

  • i know I'm a decade late, but there's a lot of good reasons you might want to use HeapAlloc directly. The most obvious is that every global allocator has a lock - having a separate memory source from the main memory source allows you to minimize contention. You can even disable the internal lock and provide customized synchronization around HeapAlloc based on your code's particular needs. – nfries88 Jan 22 '23 at 08:01