Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Free memory with explicit size

I'm looking for malloc/free-like APIs in mainstream OSs that allow me to specify an explicit size during both allocation and de-allocation. What I hope to gain by this is that the runtime might spend less memory on bookkeeping when the allocated size is already available in the program.

On e.g. windows I only found free(), _aligned_free(), and _freea(), none of which take a second argument for size.

like image 205
B_old Avatar asked Oct 09 '19 07:10

B_old


People also ask

How does free () know the size of memory to be deallocated?

When we use the dynamic memory allocation techniques for memory allocations, then this is done in the actual heap section. It creates one word larger than the requested size. This extra word is used to store the size. This size is used by free() when it wants to clear the memory space.

What happens if you try to free stack memory?

freeing something on the stack yields undefined behaviour, you're lucky this doesn't cause your program to crash, or worse. Consider that a serious bug, and delete that line asap.

Can you free memory allocated with new?

You must use delete operator to deallocate memory when it is allocated by new operator. no, you should use delete[] for new[], and delete for new.

How does malloc find free space?

In C, the library function malloc is used to allocate a block of memory on the heap. The program accesses this block of memory via a pointer that malloc returns. When the memory is no longer needed, the pointer is passed to free which deallocates the memory so that it can be used for other purposes.


1 Answers

I'm looking for malloc/free-like APIs in mainstream OSs that allow me to specify an explicit size during both allocation and de-allocation.

I'm not aware of any.

What I hope to gain by this, is that the runtime might spend less memory on bookkeeping, when the allocated size is already available in the program.

This idea certainly can work, but there are a couple of drawbacks:

  1. you have to partition allocation regions between objects whose allocated size is tracked by the caller, and objects where the allocator still needs to record that itself.

    This increases complexity and potentially memory fragmentation.

  2. you have to allocate exactly the size the program requests.

    That is, a normal allocator could decide to return a 96-byte chunk for a 64-byte request, because it's just been freed, is hot on cache, and splitting and re-coalescing chunks smaller than 64 bytes is not deemed worthwhile.

    Your allocator can't do that, in general (it is limited to rounding up to the next aligned chunk size).


Of course, there are plenty of specialized allocators that manage these tradeoffs explicitly.

Using or writing these is a perfectly normal thing to do when the general-purpose allocator isn't a good fit for your allocation patterns. But, they're generally not provided by the language or OS, because they're not general-purpose. They're provided by libraries (or by yourself).

Examples:

  1. You allocate and free a lot of objects with a previously-known fixed size.

    Write an object pool allocator for them. It doesn't need to track the allocation size, because it's always the same (often a template parameter). You don't need to explicitly track it in your code either, because it's implied by the type.

  2. Variable-sized allocations of trivial objects all with the same lifetime (eg, lots of char buffers).

    Write an arena allocator. It doesn't need to track individual allocation sizes, because you reset the entire allocator instead of freeing and re-allocating individual objects. You never explicitly delete the allocate objects, because they're trivial anyway.

NB. If you choose to integrate your allocator using new/delete overloads (and think it will benefit from the explicit size parameter) you absolutely can use the ones Maxim points out, with the following caveat:

... [explicit size overloads will be] Called instead of [the default overloads] if a user-defined replacement is provided, except that it's unspecified [which] is called when deleting objects of incomplete type and arrays of non-class and trivially-destructible class types.

like image 84
Useless Avatar answered Sep 21 '22 22:09

Useless