Ok, here's a very, very simplified explanation of a dynamic memory scheme (C gurus feel free to correct at will
). A real world scheme would be far more sophisticated.
To ease explanation I'll use two lists (These are application data, nothing to do with the operating system):
The first list (The Free List) keeps track of holes by indicating the start and length of each hole.
The second list (The Allocated List) keeps track of allocated space by indicating the start and length of each allocation.
The
heap represents the unallocated dynamic memory available to a program.
Visual is just me trying to show what's going on (o = used, . = free).
I'll make the assumptions that the dynamic memory routines will use the first hole big enough to satisfy a request, that it will request a full page of memory from the operating system whenever a large enough hole cannot be found and that my lists are sorted by address.
***
Let our program begin with no dynamic memory available or allocated.
Free List: empty
Allocated List: empty
Heap: 0 bytes
Visual: []
Now let's allocate some space.
malloc checks the Free List.
There is no 1024 byte hole available (The list is empty).
malloc asks the operating system to give it a page of memory (4096 bytes).
The operating system maps an extra page of memory into the program's page tables (Usually by extending the program's data area) and gives malloc a pointer to the new page of memory (I'll call the address this pointer indicates Address1).
A new entry is placed on the Free List indicating a hole of 4096 bytes starting at Address1.
Free List: [Address1, 4096]
Allocated List: empty
Heap: 4096 bytes
Visual: [..4096..]
The allocation is now performed.
malloc checks the Free List.
A hole of 4096 bytes starting at Address1 is found, which is large enough to satisfy the request.
This entry is removed from the Free List.
A new entry is placed on the Allocated List indicating an allocated space of 1024 bytes starting at Address1.
A new entry is placed on the Free List indicating a hole of 3072 bytes starting at Address2.
The pointer SPACE1 now points at Address1.
Free List: [Address2, 3072]
Allocated List: [Address1, 1024]
Heap: 3072
Visual: [oo1024oo|..3072..]
Now let's allocate some more space
malloc checks the Free List.
A hole of 3072 bytes starting at Address2 is found, which is large enough to satisfy the request.
This entry is removed from the Free List.
A new entry is placed on the Allocated List indicating an allocated space of 256 bytes starting at Address2.
A new entry is placed on the Free List indicating a hole of 2816 bytes starting at Address3.
The pointer SPACE2 now points at Address2.
Free List: [Address3, 2816]
Allocated List: [Address1, 1024], [Address2, 256]
Heap: 2816
Visual: [oo1024oo|oo256oo|..2816..]
Now let's free up some space.
free checks the Allocated List.
A space of 1024 bytes is found to have been allocated starting at Address1 (Which SPACE1 points at).
This entry is removed from the Allocated List.
A new entry is placed on the Free List indicating a hole of 1024 bytes starting at Address1.
Free List: [Address1, 1024], [Address3, 2816]
Allocated List: [Address2, 256]
Heap: 3840
Visual: [..1024..|oo256oo|..2816..]