A small detour β and a debt to pay. The segmentation chapter ended with physical memory full of odd-sized holes; this chapter is about living with them. The problem is fundamental to any memory manager, whether a malloc malloc The C library call requesting heap bytes (size via sizeof()); returns a pointer, or NULL on failure. A library call, not a system call. defined in ch. 14 β open in glossary library managing a processβs heap heap Memory region for explicitly requested dynamic allocations β malloc() and free() in C. defined in ch. 4 β open in glossary or the OS itself managing physical memory under segmentation.
When the managed space is divided into fixed-sized units, the job is easy: keep a list of them; a client wants one, return the first entry. (Hold that thought β itβs called paging, and itβs next chapter.) The difficulty β and the fun β arrives with variable-sized units, where external fragmentation external fragmentation Free physical memory chopped into little non-contiguous holes by variable-sized allocations, so a request can fail even though enough total free space exists β e.g. 24KB free in three chunks cannot satisfy a 20KB segment. defined in ch. 16 β open in glossary lurks:
click a region marked β for details
The free list free list The OS structure tracking unused physical memory ranges, searched at process creation and refilled at termination. defined in ch. 15 β open in glossary for this little heap has two entries β and no answer for a 15-byte request:
The free list: two 10-byte chunks, no 15-byte answer
len:10βaddr:20
len:10βNULL
The Crux: How To Manage Free Space
How should free space be managed, when satisfying variable-sized requests? What strategies can be used to minimize fragmentation? What are the time and space overheads of alternate approaches?17.1 Assumptions
The chapter draws on the great history of user-level allocators (Wilson et al.βs survey β nearly 80 pages, so you really have to be interested). The ground rules:
| what we assume | |
|---|---|
| The interface | void *malloc(size_t size) and void free(void *ptr) |
| The arena | a region historically called the heap; its free chunks tracked by a free list |
| The enemy | external fragmentation (mostly) |
| No relocation | once handed out, memory cannot be moved until freed |
| One fixed region | the allocator manages a single contiguous byte range of fixed size |
Two of these deserve a second look. The interfaceβs missing size parameter means the library must remember, for every outstanding chunk, how big it is β that bookkeeping is where the mechanisms section begins. And no relocation means compaction compaction Rearranging allocated segments into one contiguous region (stop the process, copy its data, update its segment registers) to cure external fragmentation β effective but memory- and CPU-expensive. defined in ch. 16 β open in glossary β chapter 16βs cure β is unavailable here: compacting works for an OS moving whole segments (one base register redirects everything) but not for a library whose clients hold raw C pointers. The allocator must fight fragmentation without ever moving a granted byte.
Check yourself
1.Why is free-space management trivial with fixed-sized units, but a whole chapter with variable-sized ones?
2.free(void *ptr) takes no size parameter. What does that force upon the allocation library?
3.Chapter 16 offered compaction as fragmentation's cure. Why is that off the table for a malloc library?
4.The 30-byte heap: bytes 0β10 free, 10β20 in use, 20β30 free. A request for 15 bytes arrives.