Why and how do people implement their own malloc?
I have been looking through the SDL & Quake (1/2) source code and I am wondering why the coders find a need to implement their own malloc? (I think the SDL_malloc is just for internal SDL use). And how?
Do their functions call the C malloc to allocate a huge block on the heap and then manage their memory there? Or maybe they statically allocate a huge array (but that looses flexibility)?
This is what I am most interested in (also applies to regular malloc): Do they just manage the heap themselves? If so how do they know where the heap begins and ends in memory? And how would they request more/less heap for their application?
I am asking this question because I am interested in implementing my own allocator for a hobby project.
I've implemented my own memory-allocation routines in order to implement "virtual memory" for my postscript interpreter. I needed extra features that aren't available through the C standard malloc (like garbage collection). It started as a simple "region" allocator, which isn't too difficult (using the standard realloc
to grow the region).
C is perhaps not the best language to try to do this, because it can complicate your use of pointers. With C++, you can make a new "managed-pointer" class, so your actual usage will still look normal.
For a game like Quake, the answer to 99% of "Why did they do this (this way)?" questions is performance . More frames/second, more detail/frame, quicker response. They don't want a standard allocator that uses linked-lists of metadata because they can't afford the time to traverse a list, so they write their own with a hashtable (or something even wilder).
In the past I implemented my own malloc()
(or equivalent in other languages) as a last resort measure to track down pernicious memory-related bugs. There is less need to do that sort of thing these days due to the availability of good memory diagnostics and languages that forgo the use of pointers.
In my case, I didn't do the whole job - I had my malloc()
wrap the requested memory allocation with fence data, magic numbers, allocation sequence or time information and the like to help diagnose bugs, then call the system malloc()
to actually allocate the memory.
Thus, a call p = my_malloc(nbytes)
, might generate a block of memory like this:
FF00FF00 <leading fence>
<timestamp>
<allocation sequence number>
<allocation size>
nbytes of space <this is the block of memory that p will point to>
FF88FF88 <trailing fence>
... and would also write some diagnostic information to a log file.
The call my_free(p)
would then check that the fences, timestamps, sequence numbers, etc. had not been corrupted before freeing all of the memory allocated by my_malloc()
(before and after the block pointed to by p
). my_malloc()
and my_free()
would often also write some diagnostic information to a log file that would let me match up the allocations and de-allocations and spot the sources of memory leaks. Of course, writing to a log file every time memory is allocated or de-allocated can slow the program down a lot. I often put the log file on a RAM disk to address that problem.
上一篇: 通过在堆上分配堆栈部分来避免堆栈溢出?