Hi there! š
Somebody once said that the perfect way to spend Sunday is by doing a recap of what you learned in BitesizedEngineering series on C++ Memory Allocation :)
As usual, the bitesized graphic first and then more details for those eager to understand more details:
I hope that was useful :)
So, in a nutshell, what we have is:
malloc() ā which Iād guess stands for āMemory Allocationā is a C function for allocating the memory. Given that C++ was meant as an extension of C (hence the ā++ā meaning an increment of C), malloc() exists in C++ but people generally recommend avoiding it. Hereās a nice StackOverflow thread if you want details.
ānewā expression ā which I occasionally call ākeyword newā for reasons known to myself only, is basically a C++ way for allocating memory. Iāll discuss more details about it below.
HeapAlloc() ā is part of Windowsā API and as such should be used ONLY if youāre targeting Windows only. For any other case you should really stick to ānewā.
VirtualAlloc() ā is also part of Windowsā API and represents the lowest-level API that you can interact with. It enables some amazing stuff, but also comes with a cost. Weāll discuss it below as well.
void* memory = malloc(1024);
char* memory = new char[1024];
void* memory = HeapAlloc(GetCurrentProcess(),
HEAP_GENERATE_EXCEPTIONS | HEAP_ZERO_MEMORY, 1024);
// You get back 4096 bytes (i.e. 1 page)
void* memory = VirtualAlloc(nullptr, 1024, MEM_COMMIT, PAGE_READWRITE);
As you can see above, ānewā is the only one that works with actual Data Types. All others work with raw bytes. Whatās more, HeapAlloc() and VirtualAlloc() require some additional properties, which, frankly, are the exact reason why youād likely be using them in the first place - to tweak the memory allocation behavior :)
Now letās answer the āso, what should I use?ā question. And the common answer seems to be - unless you know WHAT and WHY you are doing it, you should likely stick to expression ānewā.
One of the main benefits of the ānewā vs everything else is that it guarantees type-safety. As in - with ānewā you ensure that you get only as much bytes as you need for DATA TYPE that you want to create (remember when we discussed that C++ is all about Data Types?). On the other hand, with malloc(), HeapAlloc() and VirtualAlloc() you get back a void*
ā which is a confusing way to inform you that you get a pointer, pointing to some memory address, but itās up to you to figure out how big that SOMETHING is (hence the āvoidā part).
Another āissueā with malloc(), HeapAlloc() and VirtualAlloc() is that you get back a NULL if thereās no free memory to allocate. ānewā will generate exception, which is a preferred OOP way to handle exceptional scenarios. You can override this behavior with Heap and VirtualAlloc(), but still, itās something to keep in mind.
Yet another thing to keep in mind is that ānewā will invoke a Constructor (and Destructor), whereas other APIs wonāt do that. I guess this communicates that ānewā is much more than a Memory Allocator, right? Itās really ALL what C++ is about - Data Types. And this aligns really nicely for those coming from pretty much any managed language, where you think of ānewā as a way to construct an object :)
Finally, one cool question that one might ask is ā so, if ānewā is all about Data Types, and specifying data types, how do you allocate large chunks of memory then? And the answer is quite simple - you can use the operator new and allocate bigger chunks internally (by invoking malloc() / HeapAlloc() / VirtualAlloc() under the hood).
Fun fact btw: in Windows, ānewā actually uses malloc() under the hood, and malloc() calls HeapAlloc() which in turn calls VirtualAlloc(). You can read more about it here.
And thatād be about it for today :) Next week, as I announced before, Iām going to start sharing some insights on how CLR works (i.e. a .NETās Runtime Engine), but in parallel Iāll be working on some articles on how memory paging works, and what are User and Kernel modes in Windows (and how do they affect the memory). Until then, if you liked this, Iād appreciate if you share it! :)
Thanks for reading!
Other articles from the C++ Memory Management series: