Address Spaces and Address Translation

Learn how an operating system gives every running program its own private, protected memory. Start with the address space a program sees and the goals of memory virtualization, then follow heap requests from malloc and free down to the system calls behind them. Translate addresses step by step with base and bounds registers and with segmentation, and see how free-space managers place variable-sized requests, from first fit to buddy allocation, while keeping internal and external fragmentation in check.

IntermediateLesson 3 of 9 in Operating Systems Course

What you will learn

  1. Describe the address space a running program sees, why the operating system virtualizes memory, and the goals every memory virtualization scheme must meet.
    • Describe an address space and its layout
      Explain what an address space is, how code, heap and stack are arranged in it, and how virtual addresses differ from physical addresses.
    • Judge memory virtualization by its goals
      Evaluate a memory virtualization scheme by transparency, efficiency and protection, and separate the hardware mechanism from the operating system's policies.
  2. Distinguish stack and heap memory, request and release heap memory with the standard calls, recognize the errors they invite, and explain where the memory behind them comes from.
    • Allocate and release memory with the memory API
      Tell automatic stack memory from heap memory, use malloc and free correctly in outline, and recognize the main kinds of memory errors.
    • Explain how the allocator gets memory from the operating system
      Separate the operating system's job of managing a process's address space from the library's job of managing the heap, and describe the system calls that grow and shrink memory.
  3. Explain how hardware-based dynamic relocation turns every virtual address into a physical one, what the hardware and the operating system each contribute, and where the approach falls short.
    • Translate virtual addresses with base and bounds registers
      Apply dynamic relocation by adding the base to each virtual address and checking it against the bounds, and contrast it with static relocation.
    • Divide the work between hardware and the operating system
      List what the hardware must provide and what the operating system must do at process creation, context switches, exceptions and termination to make base and bounds work.
    • Evaluate base and bounds
      Weigh the speed and protection of base and bounds against the memory it wastes, and explain why it leads to segmentation.
  4. Give each logical segment of an address space its own base and bounds, translate and check addresses with segment registers, and judge what segmentation demands of the operating system.
    • Translate addresses segment by segment
      Place code, heap and stack independently in physical memory and translate an address by computing its offset within its segment.
    • Identify the segment an address refers to
      Determine the segment from the top bits of a virtual address or from how the address was formed, and work out the offset in binary.
    • Handle the stack, protection and sharing
      Translate stack addresses with a negative offset, use protection bits per segment, and explain how processes share code safely.
    • Support and evaluate segmentation
      Describe what the operating system must do for segmentation, compare coarse- and fine-grained segmentation, and explain the external fragmentation that limits it.
  5. Explain how a free-space manager tracks free memory and serves variable-sized requests, compare placement strategies, and reason about internal and external fragmentation.
    • Distinguish internal and external fragmentation
      Define the two kinds of fragmentation, find them in examples, and explain why a heap allocator cannot compact memory.
    • Track free space with a free list
      Split and coalesce free chunks, use headers to free memory without a size, and build the free list inside the free memory itself.
    • Compare placement strategies
      Apply best fit, worst fit, first fit and next fit to a free list and weigh their speed against the fragmentation they cause.
    • Use segregated lists, slab and buddy allocation
      Explain how size-specific lists, object caches and power-of-two buddy blocks speed up allocation, and calculate the waste and merging in buddy allocation.

Address Translation study guide

5 chapters

1

A private memory view for each process

A pointer belongs to the process that uses it. Its number alone does not identify a physical memory cell. Address spaces let several programs stay in memory while each runs with its own view of code and data. The operating system and processor must preserve that view, translate accesses quickly, and stop one program from damaging another. These goals explain both the layout a program sees and the machinery that stays hidden behind it.

1.1 The memory a process sees

A running program works with an address space: its own view of memory, with numbered byte locations. The operating system places the program's memory in the machine and arranges for its addresses to reach the right physical bytes. The layout the program sees and the layout in hardware are different things.

Why several programs stay in memory

Early systems could keep one program beside the operating system. For example, the OS might occupy the first 64 KB and the program the remaining memory. Multiprogramming kept more than one process ready, so the CPU could work while another process waited for input or output. Time sharing switched the CPU often enough to serve interactive users.

Saving one process's entire memory to disk at every switch would make switching far too slow. Keeping several processes in physical memory avoids that copying, but creates a protection problem. An address generated by one process must not let it overwrite the OS or a neighbor.

Memory sizes here follow the binary convention used in these models: 1 KB is 1,024 bytes, also written 1 KiB; 1 MB is 1,024 KB. A 16 KB address space has 16,384 byte locations, numbered 0 through 16,383. The number 16,384 is the end boundary, not a valid byte address.

Code, data, heap, and stack
RegionWhat it holdsHow it is used
CodeMachine instructionsThe CPU fetches instructions here.
Static dataGlobals and static local variablesStorage lasts for the program's run.
HeapBlocks requested while runningThe program requests and releases blocks.
StackFunction-call state and ordinary local variablesCalls create frames; returns release them.

In a classic 16 KB teaching layout, code uses the low addresses, from 0 up to the 1 KB boundary. The heap starts above the code and grows upward. The stack begins at the upper boundary and grows downward. The free gap between them gives both regions room to grow. Real layouts differ; for example, each thread has its own stack. The roles of the regions remain useful even when their positions change.

Follow a pointer to the right memory

A virtual address names a byte in a process's address space. A physical address names a byte in the machine's memory hardware. When C code prints printf("%p", (void *) &x), it prints a virtual address. The printed pointer does not reveal the physical byte storing x.

Suppose two processes both use virtual address 1,000. Each address is interpreted within its process's own address space, so the accesses can reach different physical bytes. Likewise, code at virtual address 0 need not occupy physical address 0. The OS can place it elsewhere and configure hardware translation to reach it.

The processor translates instruction fetches, loads, and stores. The OS chooses and manages the mappings, including changing physical locations while keeping the program's virtual addresses stable.

Key Takeaways

  • An address space is a process's view of memory, not its physical placement.
  • Code, static data, heap, and stack serve different storage roles.
  • Virtual addresses are interpreted within a process; equal values can reach different physical bytes.
  • A 16 KB address space has bytes 0 through 16,383 under the binary KB convention.

1.2 Transparency, efficiency, and protection

A memory system must do more than translate a number correctly. It must let ordinary programs run without managing physical placement, keep translation cheap, and enforce the boundaries that make sharing safe. These requirements are transparency, efficiency, and protection.

Preserve the program's view

Transparency means a program runs as if it had private memory. It uses its own addresses for code and data without tracking which other processes are present or where their bytes lie. The OS and hardware preserve this view behind the scenes. Moving a process in physical memory should not require the process to rewrite its pointers.

The illusion does not require a distinct physical copy of every byte for every process. For example, protected read-only code can be shared. What matters is that the sharing preserves the behavior and access rights each process is entitled to see.

Count both kinds of cost

Every instruction fetch, load, and store needs translation. Running an OS routine for each access would make ordinary execution too slow. Hardware performs the frequent operations; OS code handles setup, changes, and faults.

Space efficiency matters too. A small, fast translation mechanism can still waste substantial memory. A single base-and-bounds region reserves the unused gap between heap and stack. Segmentation avoids backing that gap, but introduces variable-sized physical regions and holes between them. Metadata, unused reserved space, and holes all affect how much useful work fits in memory.

GoalQuestion to ask
TransparencyDoes the program keep using its own addresses without managing placement?
Time efficiencyHow much work does each memory access add?
Space efficiencyHow much memory is consumed by metadata or unusable space?
ProtectionCan the process access only regions and operations it is allowed to use?
Make a bad access stop at the boundary

Without protection, a stray pointer in a text editor could overwrite another process or the kernel. Damage might appear much later in unrelated code. With enforced bounds, hardware rejects an access outside the permitted region and raises an exception. The OS handles the exception and usually ends the faulty process, commonly reporting a segmentation fault.

Protection isolates processes from one another. It does not make C memory use safe within a permitted heap region. A write past one allocated block can still hit another block owned by the same process. Process boundaries and allocator block boundaries are different boundaries.

Separate the operation from the choice

A mechanism is how an operation is carried out. Adding a base register and checking a bounds register are mechanisms. A policy chooses among possible actions: where to place a process, which free hole to use, or when to move a segment.

Keeping these separate lets the OS change its placement strategy while keeping the same hardware translation. Virtualizing memory starts with this private, protected view; it is not defined by using disk as extra memory.

Key Takeaways

  • Transparency preserves the program's view as physical placement changes.
  • Time efficiency matters on every memory access; space efficiency includes unused regions and metadata.
  • Protection isolates processes but does not enforce every heap-block boundary.
  • Mechanisms perform operations; policies choose among alternatives.
  • Hardware translates routine accesses; the OS manages translation and handles faults.
2

From C allocations to OS regions

A heap request crosses two layers of memory management. The C library finds a block for the program, while the operating system supplies and protects the regions from which blocks are carved. Following these layers explains why a pointer variable and its allocation have different lifetimes, why freeing a block may leave the process's memory use unchanged, and why a successful compilation says little about whether later heap accesses are valid.

2.1 Requesting blocks and respecting their lifetimes

A pointer variable and the memory it points to are separate objects. Understanding their lifetimes is the starting point for the C memory API. Ordinary local variables typically use automatic stack storage, heap blocks last until released, and globals and static locals have storage for the program's whole run.

Follow the allocation, not just the pointer
void f(void) {
    int x;
    int *p = malloc(sizeof(int));
}

In the usual stack layout, x and p belong to this call of f. The requested integer belongs to the heap. Returning removes the local pointer variable; it does not free the heap block. If no copy of the address remains, the program has lost access to a live allocation: a memory leak.

malloc(size) requests at least that many bytes and returns a pointer, or NULL when it cannot satisfy the request. Its bytes are not initialized for the program. For 10 integers, use malloc(10 * sizeof(int)); where an integer is 4 bytes, that requests 40 bytes. For a string, reserve its characters plus one byte for the terminating null character: malloc(strlen(s) + 1).

sizeof(a) measures the object named a. If a is a pointer, it gives the pointer's size, not the size of the allocation. An 8-byte pointer can refer to a 40-byte block.

Know what each library operation does
CallMain purpose
mallocObtain a block whose bytes are not cleared.
callocObtain a block filled with zero bytes.
reallocResize a block, possibly moving it.
freeReturn an allocated block to the allocator.

free takes the returned pointer, with no size argument. The allocator keeps size metadata, commonly in a header before the block. Pass a currently allocated block's returned pointer; an interior pointer is not a valid substitute. free(NULL) is valid and does nothing. These functions are C library routines, not system calls.

Recognize the error from the lifetime or boundary

A pointer with no valid allocation cannot be used as though it already points to storage. Reading newly allocated bytes before initializing them is an uninitialized read. Writing beyond the allocated end is a buffer overflow; omitting a string's terminator byte can cause one.

After free, old pointers to the block are dangling. Accessing through one is a use-after-free. Freeing the block again is a double free. Freeing an address the allocator did not return for a live block is an invalid free. Leaking a block is different: the block remains allocated, but the program no longer releases it when it should.

Understand what the hardware can check

Compilation can succeed despite all these errors. Hardware normally checks process regions and permissions, not each library allocation. Crossing a block boundary while staying inside the process's legal heap can have undefined behavior without an immediate fault. The program may corrupt data, crash later, read meaningless values, or appear to work. Valgrind and AddressSanitizer can detect many such errors during execution.

Key Takeaways

  • The lifetime of a heap block is separate from that of the pointer variable.
  • Use sizeof for the stored type; sizeof on a pointer does not measure its block.
  • malloc, calloc, realloc, and free are library routines.
  • A string allocation needs space for its terminating null byte.
  • free(NULL) does nothing; an interior pointer is not a valid allocated-block pointer.
  • Hardware region checks can miss block-level memory errors inside the heap.

2.2 How the allocator obtains its memory

The C library and the OS manage memory at different scales. The OS establishes regions in a process's address space and supplies their backing. The allocator divides available heap memory into blocks, records free chunks, and reuses them across calls.

Move the program break

The program break is the address just past the traditional heap's end. brk sets that boundary to a chosen address. sbrk(n) moves it by a byte increment and, on success, returns the old break. sbrk(0) reports the current break without moving it.

Suppose the break is 40,960 and the allocator successfully calls sbrk(8192). The returned value is 40,960. The new boundary is:

40,960+8,192=49,152

The added bytes occupy virtual addresses 40,960 through 49,151. The new break, 49,152, is just beyond the added region. Confusing the returned value with the new boundary shifts every later placement calculation.

Applications use the allocation library instead of moving the break directly. The library tracks which parts of its region it owns. Independent changes to that boundary can invalidate its bookkeeping.

Obtain a separate mapping

mmap can create an anonymous region: memory not tied to a file, initially filled with zero bytes. munmap removes a mapping. An allocator can use separate mappings for large allocations and return those mappings to the OS when they are freed.

In glibc, the default initial threshold for this route is 128 KB, or 131,072 bytes, and it can adjust upward. A sufficiently large allocation is typically mapped separately if it cannot be met from existing free space. This is a library policy, not a universal dividing line in the C language.

Free at the library level or the OS level
EventWhat changes
Free a small reusable blockThe allocator can serve another request from it.
Remove a separate mappingThe process no longer owns that mapped region.
Exit the processThe OS reclaims the process's memory.

A call to free usually puts a small block back into the library's pool. The process can therefore report the same memory footprint afterward. The memory is available for reuse without another OS request.

Process exit reclaims even allocations the program leaked. During a long-running server's lifetime, however, repeated leaks keep consuming its available memory. Reclamation at exit does not prevent that pressure while it runs.

Connect heap growth to translation

In the segmentation model, the heap is a contiguous physical segment. Growing it requires free physical bytes immediately above it. If those bytes are occupied, the OS may move the segment to a larger hole and update its translation state. If no suitable region is available, growth fails. If the allocator cannot obtain enough space, malloc returns NULL.

Key Takeaways

  • The OS supplies regions; the library divides them into blocks.
  • A successful sbrk returns the old break, not the new one.
  • Anonymous mmap obtains a separate zero-filled region; munmap removes it.
  • Freeing a block usually permits reuse without reducing the process's OS allocation.
  • A segmented heap needs contiguous physical space to grow.
3

Translation with base and bounds

Base and bounds turns a process-relative address into a physical one with a comparison and an addition. The simplicity makes the division of work easy to see: hardware checks every access, while the OS chooses a slot, restores translation state when switching processes, and handles faults. Following a process through these events also exposes the main cost: even unused addresses between heap and stack occupy part of its physical slot.

3.1 Checking and translating an address

Dynamic relocation translates addresses while a program runs. In the base-and-bounds model, one process occupies one contiguous physical region. Begin with equal-sized address spaces that fit in physical memory; one register pair then describes the currently running process's region.

Check the virtual address first

The base register holds the physical address of the region's first byte. The bounds register, or limit register, holds the region's size in bytes. For a nonnegative virtual address, the rule is:

0≤virtual address<bounds

If the check succeeds:

physical address=base+virtual address

Otherwise the hardware raises an exception. A size is a count, so the address equal to the bounds is already outside the region. Negative virtual addresses are invalid too.

Work through the byte boundaries

Take an 8 KB address space with base 20,480 and bounds 8,192. Its virtual bytes run from 0 to 8,191. Virtual address 1,000 passes the check and reaches physical byte 21,480. The last legal virtual byte, 8,191, reaches 28,671. Address 9,000 fails because it is at least 8,192; hardware must reject it before issuing the physical access.

Instruction fetches use the same translation as data. If an instruction at virtual 128 loads from virtual 3,000, the fetch reaches physical 20,608 and the load reaches 23,480. These are two memory accesses with two translated addresses, not one shared translation for the whole instruction.

Keep the bounds convention straight
Bounds register containsWhat is compared
Region sizeThe virtual address must be below the size.
Physical end boundaryThe translated address must be below that boundary.

The same 8 KB region has physical end boundary 28,672. Both conventions permit exactly bytes 20,480 through 28,671. Comparing physical address 21,480 with size 8,192 mixes the two conventions and wrongly rejects a legal access.

Move memory without changing pointers

The MMU, or memory management unit, performs the checks and addition. The OS can pause a process, copy its region elsewhere, and change the base. The process still uses the same virtual addresses, which is why relocation is dynamic.

Static relocation instead has a loader rewrite embedded addresses when loading code. Rewriting a reference from 1,000 to 21,480 records a physical placement in the program. Moving it later requires further rewriting, and rewriting alone does not stop a program from constructing an address outside its region.

Only add a base to a virtual address. Adding it to an already translated physical address shifts the location a second time and destroys the mapping.

Key Takeaways

  • With size bounds, check the virtual address before adding the base.
  • The legal range excludes the address equal to the bounds.
  • Instruction fetches and data accesses are both translated.
  • A physical end boundary and a byte-size bounds use different comparisons.
  • Dynamic relocation changes placement without rewriting virtual pointers.

3.2 Installing and switching translation state

The hardware holds translation registers for the process running on a CPU. The OS holds the saved state for processes that are waiting. Protection depends on giving only privileged OS code the power to change that state.

Provide the hardware operations

The CPU needs user and kernel modes, a base-and-bounds pair in its MMU, and circuits for the check and addition. It also needs privileged operations to change the pair and install exception handlers. Illegal addresses and attempts to execute privileged instructions in user mode must raise exceptions.

If a user program could change its base, it could redirect its addresses into the kernel or another process. Bounds checks would then protect the wrong region. Restricting updates is therefore part of the protection mechanism, not just an administrative convenience.

Create and run a process

At boot the OS installs its trap and exception handlers, starts the interrupt timer, and prepares its free-memory records. When a process starts, the OS finds a physical slot for its address space. With equal-sized slots, a free list can simply record which slots are unused.

The OS marks the chosen slot busy, records the process's base and bounds, loads the registers, and enters user mode. The process then runs directly on the CPU. Hardware translates ordinary accesses without calling the OS for each byte.

Restore the right pair on a context switch

A timer interrupt transfers control to the OS. It saves the old process's registers, including base and bounds, in its process control block, then restores the next process's values before returning to user mode.

Suppose A's base is 20,480 and B's base is 40,960, both with bounds 8,192. A's virtual address 1,000 reaches 21,480. After switching to B, the same virtual number reaches 41,960. Restoring the CPU registers without restoring translation state would make B access A's region using B's pointers.

The CPU has the active pair; each process has its own saved pair. Do not picture a single permanent pair for the whole machine or assume every process's pair is simultaneously active on one CPU.

Move, fault, and finish

To move A to physical address 49,152, the OS deschedules A, copies its 8 KB region, and updates A's saved base. Once A resumes with that base installed, virtual 1,000 reaches 50,152. Its virtual pointer values need no edits.

For an invalid access, hardware raises an exception and transfers execution into kernel mode at the registered handler. The OS usually terminates the offending process. On termination it returns the slot to the free list and releases process records.

Key Takeaways

  • Only privileged code can change translation registers.
  • The CPU holds active state; process control blocks hold saved state.
  • A context switch must restore base and bounds along with other registers.
  • Relocation requires pausing, copying, and updating the saved base.
  • Hardware raises access exceptions; the OS handles them.
  • Termination returns the physical slot to the free list.

3.3 Why a simple slot wastes memory

Base and bounds meets two goals cheaply: translation is transparent, and every address is checked against the allocated region. Its main weakness is the relationship between that region and the bytes the process actually uses.

Reserve the whole span

The hardware needs only an addition and a comparison on the frequent path. A fixed-size-slot allocator can also choose a free slot quickly. Neither benefit means the slot is full of useful data.

In the classic layout, code and heap sit near one end and the stack near the other. One base-and-bounds pair translates the entire interval. The unused gap between heap and stack occupies physical memory just like the useful parts.

For a 16 KB address space using 1 KB of code, 2 KB of heap, and 1 KB of stack:

used=1+2+1=4 KB unused=16−4=12 KB unused fraction=1216=75%

The waste is internal fragmentation: unused bytes inside a region already allocated to a process. It does not arise from the heap allocator choosing a poor block. Even a perfectly packed 2 KB heap leaves the large middle gap reserved.

Separate three size questions

The address space's span, the bytes currently used, and the available physical memory are different quantities. A 32-bit byte-addressed space spans 232 bytes, or 4 GB. Reserving it as one physical block requires the entire 4 GB even if the process currently uses only a few megabytes.

ConstraintConsequence
One contiguous regionSeparate free holes cannot hold one process region.
Equal-sized slotsSmall processes waste room; larger ones may not fit.
A sparse address spaceUnused virtual gaps still consume reserved physical memory.

Making slots variable-sized removes the equal-size restriction, but it does not remove the need for a contiguous hole. It also creates a placement problem: the OS must choose among free holes of different sizes. Shrinking one slot cannot preserve both low code addresses and a distant high stack address if the entire span must remain valid in the same simple mapping.

Relocate the regions separately

Code, heap, and stack do not have to be neighbors in physical memory to preserve the program's view. Giving each its own base and bounds lets the OS allocate only their used extents and leave the virtual gap unbacked. This is segmentation, the generalization of one relocation pair to several logical regions.

For the 16 KB layout above, the three used regions need only 4 KB in total before their own management overhead. The space saving comes from changing what is relocated as a unit, not from making the base-register addition faster.

Key Takeaways

  • The whole virtual span occupies a contiguous physical slot.
  • Unused space inside that slot is internal fragmentation.
  • Equal-sized slots constrain large processes and waste space for small ones.
  • Segmentation saves space by relocating used regions independently.
4

Translation with separate segments

A single translation pair reserves the gaps inside an address space. Segmentation gives code, heap, and stack independent physical homes, so only their current extents need backing. Translating an address now includes finding the segment and its offset, with an extra sign change for the downward-growing stack. The resulting flexibility supports protection and code sharing, while asking the OS to find contiguous holes for regions of different sizes.

4.1 Giving each region its own translation

A segment is a contiguous region of an address space with one purpose. In the classic model, code, heap, and stack each get a base-and-size pair. Their physical regions can be placed independently even though the process keeps its familiar virtual layout.

Map only the used extents

Use a 16 KB address space with the following placements. Sizes use binary KB, or KiB.

SegmentVirtual extentPhysical base or upper boundarySize
Code0 through 2,047Base 40,9602,048 bytes
Heap4,096 through 7,167Base 26,6243,072 bytes
Stack14,336 through 16,383Upper boundary 53,2482,048 bytes

Code and heap grow toward higher addresses; stack translation uses its upper boundary and a negative offset. The three physical regions use only 7 KB altogether. The virtual holes between them need no physical storage. A segment remains contiguous; it is the relationship between segments that no longer requires adjacency.

Translate an upward-growing segment

First identify the segment. Next compute the offset from its virtual start. Check that the offset is nonnegative and less than its current size, then add it to the physical base:

offset=virtual address−virtual segment start physical address=segment base+offset

For virtual address 500, the code offset is 500. It is below 2,048, so the access reaches physical 41,460.

For virtual address 5,000, the heap offset is:

5,000−4,096=904

The size check succeeds because 904 is below 3,072. The result is:

26,624+904=27,528

Adding the full virtual address to the heap base would produce 31,624. That mistakenly carries the heap's virtual starting position into a calculation that needs only distance within the segment.

Check the segment, not just the address-space span

Virtual address 7,500 still fits in 14 bits, but that does not make it legal. Its heap offset is 3,404, beyond the current 3,072-byte extent. Hardware raises an exception. An address can therefore lie inside the overall address-space span and still lie outside every valid region.

The term segmentation fault originated with invalid segmented accesses and remains in use for illegal accesses on systems with other translation schemes. The error name alone does not identify the translation mechanism in the machine.

Key Takeaways

  • Each segment has its own base and size.
  • The upward-segment offset is measured from that segment's virtual start.
  • Add only the checked offset to the physical base.
  • An address within the overall virtual span can still fault.
  • Unused virtual gaps between segments require no physical backing.

4.2 Selecting the segment and extracting its offset

Before hardware can use a segment's base and size, it must decide which segment an access names. An explicit design puts that choice in address bits. An implicit design derives it from the way the CPU formed the address.

Split a 14-bit address

Give the top two bits to the segment number and the low twelve bits to the offset. The two-bit field has four possible values. Use 00 for code, 01 for heap, and 11 for stack; leave 10 unused.

The offset field can represent 4,096 different values, from 0 through 4,095. Each segment's maximum virtual window is therefore 4 KB, even when the segment's current valid extent is smaller. Maximum capacity and current size are different limits.

For virtual address 5,000, the 14-bit representation is:

01 0011 1000 1000

The leading 01 selects the heap. The remaining 0011 1000 1000 is decimal 904. With heap size 3,072 and physical base 26,624, the offset passes the size check and reaches physical 27,528.

Use a mask and shift

The same split can be expressed as code:

segment = (va & 0x3000) >> 12;
offset = va & 0x0FFF;

The mask 0x3000 keeps the two selector bits; shifting by twelve moves them to the low positions to give the segment number. The mask 0x0FFF clears those selector bits and keeps the offset. For va = 0x1388, the results are segment 1 and offset 0x388, or 904.

Do not add 0x1388 directly to the heap base. That includes both the segment selector and the offset. The selector chooses the registers; only the offset participates in the within-segment translation. The resulting physical address does not need to retain the selector bit pattern.

Recognize the cost of the split

A two-bit selector creates four windows. Leaving 10 unused makes one quarter of the 16 KB virtual span unavailable. No segment can grow beyond its 4 KB window just because more physical memory becomes free. Other designs can use a different split; combining code and heap into one segment allows a single selector bit to distinguish it from stack.

Let the access type choose instead

In an implicit design, instruction fetches use the code segment because their address comes from the program counter. Stack-pointer or frame-pointer references use the stack segment. Other accesses use the heap segment in this simplified model.

Selection methodWhere the choice comes from
ExplicitA segment field inside the virtual address
ImplicitThe register or access type that formed the address

Key Takeaways

  • Selector bits choose translation state; offset bits locate a byte within the window.
  • Twelve offset bits allow a maximum segment window of 4,096 bytes.
  • Masking and shifting separate the fields without carrying selector bits into the base addition.
  • Implicit selection uses the source of an address, such as the program counter or stack pointer.

4.3 Translating the stack and enforcing permissions

The stack grows toward lower addresses. Its translation needs a direction bit as well as a base and size. In this model, 1 marks upward growth and 0 downward growth. Access permissions add another independent check: a byte can be within bounds and still forbid the requested operation.

Treat the stack base as an upper boundary

For an upward-growing segment, the base names its first physical byte. For a downward-growing segment, the base names the boundary just above its highest physical byte. In the running layout, stack base 53,248 and size 2,048 cover physical bytes 51,200 through 53,247.

For the 4 KB stack window selected by 11, convert the twelve-bit offset field into a negative displacement:

displacement=offset field−4,096

The field ranges from 0 to 4,095, so this displacement is always negative. It is valid when its magnitude does not exceed the current stack size. Then add the signed displacement to the base.

Work through a legal stack access

Virtual address 15,500 selects stack. Its window starts at virtual 12,288, so its offset field is 3,212. Convert the field:

3,212−4,096=−884

The depth 884 is within size 2,048. Translation gives:

53,248−884=52,364

Adding positive 3,212 to the base would point above the stack. The field is not yet the displacement required for a downward-growing segment.

Virtual address 13,000 instead gives field 712 and displacement −3,384. Its depth exceeds 2,048, so hardware faults. If the OS successfully grows the stack, increasing its size can make more low addresses valid.

Keep the lower endpoint

A displacement of −2,048 reaches the stack's lowest byte, 51,200, and is legal. A displacement of −2,049 is outside. The downward check therefore includes the magnitude equal to the size. This matches the upward rule's byte count even though that rule excludes an offset equal to the size: the upward base is a byte, while the downward base is an end boundary.

Check the requested operation

Protection bits record read, write, and execute permission. Code is typically read-execute; heap and stack are typically read-write. A write to read-execute code faults even when its offset is valid. Executing data also faults when execute permission is absent.

Read-only code can be shared. The OS can point two processes' code segments at the same physical region and deny writes in both. The instruction bytes occupy one physical copy, while each process keeps a separate heap and stack.

Key Takeaways

  • A downward segment's base marks its upper boundary, not a stored byte.
  • Subtract the maximum window size from the offset field to get the negative displacement.
  • The stack's lowest byte is legal when displacement magnitude equals current size.
  • Both bounds and the requested operation must pass hardware checks.
  • Read-only code sharing saves physical memory while private writable regions remain separate.

4.4 Managing variable-sized physical segments

Segmentation replaces one large region with several smaller ones. This avoids backing empty virtual gaps, but the OS must now place and grow regions of different sizes while preserving each process's translation state.

Save every part of the mapping

At a context switch, base and size alone are no longer enough. The OS saves and restores each segment's base, size, growth direction, and permissions. Restoring a stack with the wrong direction or code with the wrong permissions would change the meaning of otherwise identical addresses.

When an allocator needs more heap space, the OS must extend the physical heap segment. Free bytes immediately above it allow direct growth. Otherwise the OS can move it to a suitable larger hole and update its base. If it cannot obtain a suitable region, growth fails.

Choose the granularity
SchemeOrganizationManagement consequence
Coarse-grained segmentationA few regions such as code, heap, stackA small set of segment registers describes the process.
Fine-grained segmentationMany regions, perhaps one per data structureA memory-resident segment table supports more sharing and protection choices.

Multics used fine-grained segmentation. More segments allow smaller units of control, but require more translation metadata and management.

Find a sufficiently large hole

Variable-sized physical segments leave variable-sized free holes as processes start, grow, and exit. External fragmentation occurs when enough bytes are free in total, but no single hole can hold the requested segment.

Suppose the free holes are 8 KB, 6 KB, and 10 KB. Their total is 24 KB. A 12 KB heap segment still cannot fit: the largest available hole is only 10 KB. Joining the holes on paper does not make their physical addresses adjacent.

Compaction can repair this layout. The OS pauses processes, copies segments next to one another, and updates their bases. Virtual addresses keep working because translation hides the physical moves. The result is a large contiguous free region, but the copying is costly and new allocations can fragment memory again.

Placement policies such as first fit and best fit try to limit bad leftovers without copying. No variable-sized placement policy removes external fragmentation for every request sequence. A single large segment can also waste space within its own extent when only scattered parts are used.

Recognize the model in modern systems

Paging divides memory into fixed-sized pieces and avoids requiring each logical region to occupy one physical hole. The segmentation model remains useful for understanding regions, protection, and sharing. In x86-64's 64-bit mode, ordinary code, data, and stack segmentation bases act as zero and their limits are not checked; FS and GS retain useful bases for per-thread or per-CPU data. An illegal-access message called a segmentation fault does not mean the classic three-segment model is active.

Key Takeaways

  • Context switches restore direction and permissions as well as bases and sizes.
  • Fine-grained segmentation provides more independent regions through a segment table.
  • External fragmentation depends on individual hole sizes, not just their total.
  • Compaction moves physical segments and updates bases, preserving virtual pointers.
  • Placement policies reduce fragmentation without guaranteeing its removal.
  • Ordinary x86-64 translation differs from classic segmentation.
5

Managing free chunks and their costs

An allocator must know which bytes are free and choose a block that can hold each request. Splitting and coalescing change the free list; placement policies change which holes survive for later requests. Headers, alignment, and power-of-two rounding add costs of their own. Tracing these changes makes it possible to explain allocation failures, compare policies, and see why specialized caches and buddy allocation trade flexibility for speed.

5.1 Locating the waste inside or between chunks

Free-space management records available memory and chooses where each request goes. Equal-sized requests can use a list of interchangeable chunks. Variable sizes are harder: both a heap allocator and an OS placing segments must find a contiguous chunk large enough for the next request.

Locate external fragmentation

Consider a 60-byte region with free bytes 0–19, an allocated chunk at 20–39, and free bytes 40–59. Forty bytes are free, but neither free hole can hold a 25-byte request. The live middle chunk prevents treating those holes as one region.

This is external fragmentation: capacity is free outside allocated chunks, but its arrangement makes it unusable for a particular contiguous request. The free bytes have not disappeared. They can still serve smaller requests or become useful when intervening chunks are freed.

Locate internal fragmentation

An allocator that rounds requests to multiples of 16 gives a 20-byte request a 32-byte chunk. The 12 extra bytes sit inside an allocation already handed out. That waste is internal fragmentation.

The unused heap–stack gap in a base-and-bounds slot is another example. Buddy allocation introduces the same kind of waste when it rounds to powers of two. The level of management differs, but the location of the unused space is the defining feature.

WasteWhere it sitsWhat makes it costly
Internal fragmentationInside an allocated regionReserved bytes exceed the useful content.
External fragmentationIn separate free holesNo individual hole fits the requested extent.

One allocator can suffer both. Rounding a request may waste bytes inside its chunk while other free chunks remain separated elsewhere.

Merge free neighbors without moving live data

Coalescing merges physically adjacent free chunks. If the middle chunk in the 60-byte region is freed, all three pieces can join into one 60-byte hole. If the middle chunk stays allocated, coalescing cannot cross it. Merging reduces external fragmentation but does not guarantee a large enough hole for every request.

Adding more memory to a heap can relieve pressure, but does not change the addresses of existing live blocks. Their placement can still leave unusable small gaps.

Explain why the OS can compact segments

The OS may copy physical segments and update their bases. Programs keep virtual addresses, so the mapping can hide those moves. A general C heap allocator lacks a translation layer between returned pointers and locations within the heap. A program may have copied a pointer into many objects, and the allocator cannot discover and rewrite every copy.

Moving a live heap block on its own would leave those pointers aimed at its old location. Consequently, ordinary malloc management keeps live blocks at their returned addresses until they are freed. It must manage fragmentation through placement, reuse, splitting, and merging free space.

Key Takeaways

  • Internal waste lies inside allocations; external fragmentation lies in separated free holes.
  • Total free capacity does not prove that a contiguous request can fit.
  • Coalescing merges adjacent free chunks without moving live blocks.
  • OS segment relocation can preserve pointers through translation; ordinary C heap compaction cannot.

5.2 Following headers, splits, and merges

A free list records free chunks by address and size. Allocating splits a chunk or removes it from the list; freeing returns a chunk and may merge it with neighbors. The size convention matters: a recorded size may mean usable payload or the whole chunk including metadata.

Split and coalesce simple ranges

Ignore headers first. In a 60-byte region with free entries (0, 20) and (40, 20), an 8-byte request placed at the start returns address 0. The remaining entries are (8, 12) and (40, 20).

Starting again from the original layout, free the middle allocated bytes 20–39. Without merging, three 20-byte entries still cannot individually serve a 30-byte request. Coalescing adjacent ranges produces (0, 60), which can. Address order helps the allocator recognize neighbors; list adjacency alone is not enough unless their physical ranges touch.

Recover the header from the user pointer

free(ptr) receives no size. A simple allocator stores a size header immediately before the payload, sometimes with a checking value or magic number. Subtracting the header length finds the metadata.

With a 16-byte header, a 96-byte request occupies 112 bytes in all. The program receives a pointer 16 bytes after the chunk start. Freeing it returns the whole 112-byte extent, including the header, for future management. Alignment can add rounding; these example sizes already meet 16-byte alignment.

Trace an embedded free list

Suppose a 4,096-byte heap starts at 32,768. A free node uses 16 bytes and records usable bytes after the node. Initially it records 4,080 usable bytes.

Three 96-byte requests each consume 112 bytes:

RequestHeader addressReturned pointer
First32,76832,784
Second32,88032,896
Third32,99233,008

The remaining free node starts at 33,104. Its usable size is 3,744 bytes. The accounting is:

336+16+3,744=4,096

Freeing pointer 32,896 finds header 32,880. That chunk becomes a free node with 96 usable bytes. It cannot join the tail node at 33,104 because the third allocation lies between them. When all three allocations are freed and coalesced, one node again describes 4,080 usable bytes. Absorbing the old interior headers makes their bytes available inside the merged extent.

Keep bookkeeping inside the managed region

Embedded list nodes live in free memory itself, so managing the list does not require a separate allocation for every entry. The node contains a size and a link to the next free chunk. If no chunk fits, the allocator can request more memory with sbrk or mmap; failure to obtain enough memory leads to NULL.

An overflow can overwrite a neighboring header or node. That explains why the visible failure may occur during a later malloc or free, after the write that damaged the list.

Key Takeaways

  • Distinguish usable size from total extent including metadata.
  • A 16-byte header makes a 96-byte request consume 112 bytes.
  • Find an allocation header by subtracting its size from the returned pointer.
  • Splitting preserves a usable remainder; coalescing requires adjacent free extents.
  • Embedded nodes store list metadata in the free chunks themselves.
  • A live intervening chunk prevents merging.
  • Overwriting bookkeeping can cause failures in later allocator calls.

5.3 Choosing a free chunk

A placement policy chooses among chunks large enough for a request. Different choices leave different holes for future requests. Search time matters along with fragmentation, and no policy wins for every workload.

Compare the search rules
PolicyChoiceMain tradeoff
Best fitSmallest chunk that fitsA full simple-list search may leave tiny slivers.
Worst fitLargest chunkA full simple-list search may consume a valuable large hole.
First fitFirst fitting chunk in list orderStops early, but small leftovers collect near the front.
Next fitFirst fitting chunk from a saved search positionSpreads searches across the list, wrapping when needed.

For best and worst fit, a plain unsorted list needs a full search. Other structures can find suitable sizes more quickly. First fit means first in the chosen list order, which need not mean smallest address unless the list is address-ordered.

Trace the first request

Take free chunks of 30, 12, 50, and 20 bytes in address order. Ignore headers and assume splitting can preserve each leftover. An 18-byte request changes the list as follows:

  • Best fit uses 20 and leaves 30, 12, 50, 2.
  • Worst fit uses 50 and leaves 30, 12, 32, 20.
  • First fit uses 30 and leaves 12, 12, 50, 20.
  • Next fit starting at the fourth chunk uses 20 and leaves 30, 12, 50, 2.

Next fit needs a starting position to determine its choice. The name alone does not imply the list's first entry. A trace must retain that search state between requests.

See why the next request changes the verdict

A following request asks for 45 bytes. Best fit and first fit both preserved the 50-byte chunk, so both succeed. Worst fit's largest remaining chunk is 32 bytes, so it fails despite 94 bytes free overall:

30+12+32+20=94

This failure is external fragmentation. The earlier decision broke the only sufficiently large hole. Conversely, best fit left a 2-byte sliver that may be too small for useful future requests. An immediate small remainder is not evidence that a policy will use space well over the full request sequence.

Balance policy and data structure

Scanning thousands of entries can be expensive even when each placement is good. Practical allocators group chunks by size or use searchable structures such as balanced trees. An address-ordered list also supports coalescing by making physical neighbors easier to find.

The allocation mechanism—find, split, update metadata—can stay the same while the policy changes. To compare policies fairly, trace the same requests and frees, keep overhead rules fixed, and account for both the resulting holes and the amount of search.

Key Takeaways

  • Best fit chooses the smallest sufficient chunk; worst fit chooses the largest.
  • First fit depends on list order; next fit also depends on the saved search position.
  • A choice that serves one request can prevent a later larger request.
  • No placement policy is best for every workload.
  • Data structures affect search cost independently of the selection rule.

5.4 Reusing sizes, objects, and buddy blocks

General free-list search is flexible but can be expensive. Specialized allocators make common requests predictable by grouping sizes, retaining reusable objects, or restricting block sizes to powers of two.

Reuse popular sizes and initialized objects

Segregated lists keep separate free lists for popular sizes, with a general allocator for other requests. Serving a common size can take a chunk directly from its list. Equal-sized chunks do not create external fragmentation among themselves, but dividing capacity among lists is a policy choice: spare chunks of one size may not serve another size.

A slab allocator keeps an object cache for a recurring kernel object type, such as an inode, lock, or process descriptor. A slab is divided into objects of that type. The cache obtains more slabs when needed and can return an entirely free slab to a general allocator. Jeff Bonwick designed this approach for Solaris.

The cache keeps freed objects in an initialized state, avoiding repeated setup and destruction. That saves time beyond the search itself.

Split a buddy region

A binary buddy allocator starts with a power-of-two region and rounds each request to a power-of-two block size. It repeatedly splits a free block into equal halves until a half just fits. The two halves from one split are buddies.

For a 5 KB request in a 64 KB region, round 5 KB to 8 KB. Split 64 into two 32 KB blocks, then the chosen 32 into two 16 KB blocks, then the chosen 16 into two 8 KB blocks. Returning the first 8 KB block leaves free buddies at offsets 8 KB, 16 KB, and 32 KB, with sizes 8 KB, 16 KB, and 32 KB respectively.

The allocation wastes 3 KB inside its 8 KB block. This is internal fragmentation, accepted in exchange for regular splitting and merging.

Find the one legal merging partner

Using offsets measured from the managed region's start:

buddy offset=block offset⊕block size

Exclusive OR flips the bit corresponding to the block size. For an 8 KB block at offset 0, its buddy is at offset 8,192. For a 16 KB block at offset 16,384, its buddy is at 0.

When the first 8 KB block is freed, it merges with its free 8 KB buddy. The resulting 16 KB block can merge with its free buddy, then the resulting 32 KB block can merge again. Merging stops if the required same-size buddy is in use. Being adjacent and free is insufficient when two blocks are not buddies from the same split.

A 20 KB request receives 32 KB, wasting 12 KB, or 37.5% of the block. Linux combines physical-memory buddy allocation with slab-style object caches. Multithreaded allocators also use local caches or multiple arenas to reduce waiting for one shared allocation lock; glibc, jemalloc, and tcmalloc use versions of these ideas.

Key Takeaways

  • Segregated lists speed common-size requests.
  • Slab caches reuse recurring object types and can avoid repeated initialization.
  • Buddy allocation rounds to powers of two and splits into equal halves.
  • Buddy identity uses region-relative offset XOR block size.
  • Only a free same-size buddy can merge at each level.
  • Power-of-two rounding trades internal fragmentation for simple management.

Address Translation examples

5 Walkthroughs

1

Follow a pointer through a private memory view

8 steps
Connect the process layout to translation, isolation, and efficient execution.
  1. 1
    IntroductionOne machine, several memory views

    Several processes can stay in physical memory while the CPU switches among them. Each needs a stable view of its own instructions and data, even as other processes start, stop, or move.

    An address space supplies that view. The pointer a process uses belongs to this view; the OS and hardware determine the physical byte reached by the access.

  2. 2
    ExplanationPlace the program's contents

    Code stores instructions, static data stores globals and static locals, the heap stores requested blocks, and the stack stores function-call state.

    In the classic layout, the heap grows upward and the stack downward into a gap. With binary sizes, 1 KB means 1,024 bytes, also called 1 KiB. A 16 KB space has bytes 0 through 16,383; its upper boundary is not itself a byte in the space.

  3. 3
    ExampleGive the same number two meanings

    Process A and process B both use virtual address 1,000. A's translation can send it to one physical byte while B's sends it to another. The pointer number alone does not identify shared storage.

    Likewise, printing &x shows a virtual address. Moving the underlying physical storage need not change the pointer value the program sees.

  4. 4
    ChallengeInterpret two printed pointers

    Two processes print the same pointer value. Must they be reading the same physical byte? Explain what determines the destination.

    ---reveal---

    No. Each printed pointer is interpreted in its own process's address space. The active mapping determines the physical destination, so equal virtual numbers can reach different bytes. The same physical byte would require mappings that actually share storage.

  5. 5
    ExplanationTranslate quickly and enforce boundaries

    Transparency preserves the program's private view. Time efficiency keeps translation cheap on every fetch, load, and store. Space efficiency limits metadata and wasted capacity. Protection stops unauthorized accesses.

    Hardware handles routine translation. The OS configures the mappings, chooses placements, and takes control when an access raises an exception.

  6. 6
    ChallengeSeparate the choice from the operation

    A memory manager switches from choosing the first suitable hole to choosing the smallest suitable hole. Hardware still checks bounds and adds a base. Did the mechanism or the policy change?

    ---reveal---

    The placement policy changed: it now makes a different choice among holes. The translation mechanism is unchanged. The same hardware can translate and protect a region regardless of which suitable hole the OS chose.

  7. 7
    ChallengeConnect movement to protection

    An OS moves a paused process to a new physical region but preserves its pointer values. Why does that require both translation and control over who can change the mapping?

    ---reveal---

    Translation redirects the unchanged virtual pointers to the copied bytes. Only privileged OS code may install the new mapping; otherwise a process could redirect itself into another process or the kernel. Stable pointers supply transparency, while controlled mappings preserve isolation.

  8. 8
    RecapRead the pointer in its process

    An address space organizes a process's code and data independently of physical placement. A virtual pointer becomes meaningful through the running process's mapping.

    Evaluate a design by the view it preserves, the time and space it costs, and the access boundaries it enforces. Policies choose placements; mechanisms carry out translation and checks.

2

Trace a heap request across the library and OS

12 steps
Track block lifetimes, library calls, program-break growth, and separate mappings.

Save this lesson to follow every Walkthrough step by step.

  1. 1
    IntroductionKeep the two owners in view
  2. 2
    ExampleSeparate a pointer from its allocation
  3. 3
    ExplanationRequest enough bytes
  4. 4
    ChallengePredict what survives a return
  5. 5
    ExplanationRelease only a live block
  6. 6
    Key InsightA legal region can contain an illegal object access
  7. 7
    ExplanationGrow a region, then divide it
  8. 8
    ChallengeLocate the newly added bytes
  9. 9
    ConnectionFree a block or remove a mapping
  10. 10
    ChallengeExplain a stable footprint
  11. 11
    ChallengeTrace growth through segmentation
  12. 12
    RecapTrack lifetime and ownership separately
3

Run and move a base-and-bounds process

13 steps
Translate accesses, restore the right mapping, and calculate reserved-space waste.

Save this lesson to follow every Walkthrough step by step.

  1. 1
    IntroductionDescribe one physical slot
  2. 2
    ExplanationApply the size convention
  3. 3
    ExampleTranslate the fetch and the load
  4. 4
    ChallengeCheck the last byte
  5. 5
    TipRecognize the alternate bounds register
  6. 6
    ExplanationProtect the translation registers
  7. 7
    ExampleSwitch the memory view with the CPU state
  8. 8
    ChallengeFind a missing restore
  9. 9
    ConnectionMove a process without rewriting pointers
  10. 10
    ExampleMeasure the unused span
  11. 11
    ChallengeChoose the unit of relocation
  12. 12
    ChallengeKeep the bound after a move
  13. 13
    RecapKeep both coordinates and costs straight
4

Translate code, heap, and a downward stack

17 steps
Extract segment fields, check exact endpoints, and connect sharing to physical placement.

Save this lesson to follow every Walkthrough step by step.

  1. 1
    IntroductionSplit the process into logical regions
  2. 2
    ExplanationSet up the running layout
  3. 3
    ExampleFind the heap offset
  4. 4
    ChallengeTest a byte beyond the heap
  5. 5
    ExplanationUse selector bits to choose registers
  6. 6
    ExampleExtract both fields
  7. 7
    ChallengeSeparate capacity from current use
  8. 8
    ConnectionLet the access choose a segment
  9. 9
    ExplanationMeasure downward from an upper boundary
  10. 10
    ExampleCompute a signed stack displacement
  11. 11
    ChallengeInclude the stack's lowest byte
  12. 12
    Key InsightCheck permission after finding a valid location
  13. 13
    ExplanationRestore more than a base
  14. 14
    ChallengeCount holes separately
  15. 15
    ConnectionUnderstand compaction's limits
  16. 16
    ChallengeMove a shared segment safely
  17. 17
    RecapFind the region before the physical byte
5

Trace free chunks and choose allocation policies

18 steps
Follow metadata, compare placement traces, and split and merge buddy blocks.

Save this lesson to follow every Walkthrough step by step.

  1. 1
    IntroductionAsk whether one chunk fits
  2. 2
    ExampleLocate the unused capacity
  3. 3
    ChallengeTest what merging can accomplish
  4. 4
    ConnectionExplain why live pointers prevent heap compaction
  5. 5
    ExplanationAccount for the header
  6. 6
    ExamplePlace three blocks
  7. 7
    ExampleCheck the remaining extent
  8. 8
    ChallengeRecover a header and an extent
  9. 9
    ExplanationLet policy choose the chunk
  10. 10
    ExampleCompare the first choice
  11. 11
    ChallengeLook ahead to the next request
  12. 12
    ConnectionMake common requests predictable
  13. 13
    ExampleRound and split a buddy region
  14. 14
    ExplanationFind the matching buddy
  15. 15
    ChallengeFollow the merge levels
  16. 16
    Key InsightPay for simplicity inside the block
  17. 17
    ChallengeSeparate placement from merging
  18. 18
    RecapTrace both the layout and the accounting

Address Translation practice questions

50 Practice Questions in 5 sets

Set 1: Address spaces, checks, and first allocations10 Practice Questions

Question 1 of 10

Two processes each print a pointer whose numeric value is 2,400. What does this tell you about their physical storage?
  1. Their bytes must occupy the same physical address in memory.
  2. Their mappings can place the bytes at different physical addresses.
  3. Their bytes must have identical contents at that virtual address.
  4. Their virtual addresses must change before either process runs.
Show answerHide answer
Answer: B
Each pointer is interpreted in its own process's address space, so equal virtual values can reach different physical bytes. Equal numbers do not prove shared storage. Shared storage would require the mappings to name the same underlying region.

Question 2 of 10

An OS changes how it selects a free process slot while keeping the same bounds-checking hardware. What has changed?
  1. The user-mode privilege rule has changed.
  2. The placement policy has changed.
  3. The process address width has changed.
  4. The relocation mechanism has changed.
Show answerHide answer
Answer: B
The policy chooses a slot from the available alternatives. The mechanism still checks bounds and adds the selected base exactly as before. Calling this a new relocation mechanism confuses the decision about placement with the operations that enforce it.

Question 3 of 10

A local pointer is the only usable reference to an allocated block. Its function returns without freeing the block or saving the pointer. What memory error results?
  1. A memory leak from an unreachable allocation.
  2. A use-after-free caused by the function return.
  3. A buffer overflow into the next heap block.
  4. A double free of the pointer's former block.
Show answerHide answer
Answer: A
The heap allocation remains live after the local pointer disappears. With no saved reference, the program cannot release or reuse that block through its allocation address. Returning from a function does not itself free heap storage, so this is not use-after-free.

Question 4 of 10

A program allocates storage for 12 integers, each 4 bytes. Its pointer type occupies 8 bytes. How many bytes does sizeof(p) report when p holds the allocation address?
  1. 4 bytes
  2. 48 bytes
  3. 12 bytes
  4. 8 bytes
Show answerHide answer
Answer: D
The operand of sizeof(p) is the pointer object, whose size is given as 8 bytes. The allocation holds 48 bytes, but sizeof does not follow a pointer to measure a heap block. Using the allocation's size here confuses the pointer with its target.

Question 5 of 10

A process has base 18,000 and size bounds 3,000. What happens when it loads from virtual address 2,750?
  1. It reads physical byte 2,750.
  2. It faults because 20,750 exceeds 3,000.
  3. It reads physical byte 20,750.
  4. It reads physical byte 15,250.
Show answerHide answer
Answer: C
Virtual 2,750 is below the 3,000-byte bounds, so the access is legal. Adding base 18,000 gives physical 20,750. Comparing that physical result with the byte-size bounds would wrongly reject an address whose virtual offset fits.

Question 6 of 10

With base 24,000 and size bounds 4,500, what happens to an access at virtual address 4,500?
  1. Hardware extends the region by one byte.
  2. Hardware accesses physical byte 28,500.
  3. Hardware rejects the access as out of bounds.
  4. Hardware accesses physical byte 28,499.
Show answerHide answer
Answer: C
A 4,500-byte region contains virtual bytes 0 through 4,499. The virtual address equal to the size is the first byte beyond it, so hardware raises an exception. Adding the base before accepting the check does not make that excluded boundary a legal byte.

Question 7 of 10

An upward-growing heap begins at virtual 2,048, has size 1,536, and has physical base 30,000. Where does virtual address 2,900 translate?
  1. Physical byte 31,536.
  2. Physical byte 30,852.
  3. Physical byte 27,952.
  4. Physical byte 32,900.
Show answerHide answer
Answer: B
The heap offset is 852, found by subtracting virtual start 2,048 from address 2,900. It is below size 1,536, so adding it to base 30,000 gives 30,852. Adding the full virtual address would incorrectly include the virtual start in the relocation.

Question 8 of 10

A segmented address uses two high selector bits and ten low offset bits. What maximum byte window does one segment have?
  1. 1,024 bytes
  2. 1,023 bytes
  3. 4,096 bytes
  4. 256 bytes
Show answerHide answer
Answer: A
Ten offset bits represent 1,024 byte positions, numbered 0 through 1,023. The two selector bits choose a segment instead of enlarging its offset range. Using all twelve bits to obtain 4,096 confuses the full address space with one segment's window.

Question 9 of 10

A heap has free holes of 22 and 34 bytes separated by a live block. Headers are ignored. Why can a 40-byte contiguous allocation fail?
  1. Neither free hole alone can hold 40 bytes.
  2. Both holes must be discarded before reuse.
  3. The request exceeds all free capacity combined.
  4. The 56 free bytes lie inside allocated chunks.
Show answerHide answer
Answer: A
The holes total 56 bytes, but the allocator needs one uninterrupted 40-byte extent. The larger hole is only 34 bytes, and the live block prevents merging across it. This is external fragmentation; the free bytes are outside allocations, not internal waste.

Question 10 of 10

A 512-byte heap starts at 16,000. Every allocation has a 16-byte header, with no rounding. First fit allocates payloads of 48 then 64 bytes from the low end. The first block is freed. What pointer is returned for a new 56-byte payload?
  1. 16,144
  2. 16,016
  3. 16,080
  4. 16,160
Show answerHide answer
Answer: D
The first two chunks occupy 64 and 80 bytes, so the free tail starts at 16,144. The freed first chunk has only 64 total bytes and cannot hold a 56-byte payload plus its header. The new chunk uses the tail, returning 16,160; 16,144 is its header address.
Set 2: Process switches and placement decisions10 Practice Questions

Save this lesson to see every answer and practice every set.

Question 1 of 10

Which process region holds an ordinary function call's return address in the usual layout?
  1. The code region.
  2. The heap.
  3. The stack.
  4. The static data region.
Show answerHide answer

Save this lesson to see this answer.

Question 2 of 10

The program break is 57,344. A successful sbrk(4096) extends the heap. What are the returned value and new break?
  1. Returned 61,440; new break 61,440.
  2. Returned 57,344; new break 53,248.
  3. Returned 57,344; new break 61,440.
  4. Returned 4,096; new break 61,440.
Show answerHide answer

Save this lesson to see this answer.

Question 3 of 10

A server frees several small blocks, but its OS memory footprint stays unchanged. How can that be normal?
  1. The library keeps the regions for future block requests.
  2. The pointers remain live because the OS footprint is unchanged.
  3. The OS delays making the blocks reusable until process exit.
  4. The freed blocks must each still contain an active allocation.
Show answerHide answer

Save this lesson to see this answer.

Question 4 of 10

Process R uses base 12,000 and process S uses base 28,000, both with bounds 2,000. After a switch to S, a legal access at virtual 640 reaches 12,640. What saved state was not correctly restored?
  1. The outgoing process's stack contents.
  2. The incoming process's base register.
  3. The incoming process's virtual address width.
  4. The incoming process's bounds size.
Show answerHide answer

Save this lesson to see this answer.

Question 5 of 10

A 32 KB process slot holds 3 KB of code, 5 KB of heap, and 4 KB of stack. What percentage of the reserved slot is unused?
  1. 62.5%
  2. 37.5%
  3. 75%
  4. 20%
Show answerHide answer

Save this lesson to see this answer.

Question 6 of 10

A downward stack has a 4,096-byte selector window, physical base 60,000, and current size 1,500. Its offset field is 3,200. What happens to a read?
  1. It faults because 3,200 exceeds 1,500.
  2. It reaches physical byte 63,200.
  3. It reaches physical byte 58,500.
  4. It reaches physical byte 59,104.
Show answerHide answer

Save this lesson to see this answer.

Question 7 of 10

Two processes share a read-execute code segment at the same physical base. One attempts an in-bounds store into it. What should happen?
  1. Both processes' code changes at that byte.
  2. Only the writer's private code copy changes.
  3. A permission exception blocks the store.
  4. The store succeeds because its offset is legal.
Show answerHide answer

Save this lesson to see this answer.

Question 8 of 10

Free holes in address order are 44, 18, 70, and 32 bytes. Headers are ignored; each allocation takes the low end. Which policy serves requests of 30 then 65 bytes when neither block is freed between requests: first fit, best fit, or worst fit?
  1. First fit and worst fit succeed; best fit fails.
  2. Best fit and worst fit succeed; first fit fails.
  3. All three policies serve both requests successfully.
  4. First fit and best fit succeed; worst fit fails.
Show answerHide answer

Save this lesson to see this answer.

Question 9 of 10

Next fit sees holes of 16, 48, 24, and 40 bytes. Its search starts at the fourth hole and wraps if needed. Headers are ignored. Which hole serves a 30-byte request?
  1. The 24-byte third hole.
  2. The 48-byte second hole.
  3. The 16-byte first hole.
  4. The 40-byte fourth hole.
Show answerHide answer

Save this lesson to see this answer.

Question 10 of 10

A buddy allocator starts with one free 32 KB region and ignores headers. It allocates two 6 KB requests from the lowest available offsets, then frees the first. What is the largest available block immediately afterward?
  1. 24 KB
  2. 16 KB
  3. 32 KB
  4. 8 KB
Show answerHide answer

Save this lesson to see this answer.

Set 3: Tracing boundaries and allocator state10 Practice Questions

Save this lesson to see every answer and practice every set.

Question 1 of 10

A system checks every virtual address correctly but enters kernel code on every legal load. Which virtualization goal is most directly weakened?
  1. Placement transparency.
  2. Space efficiency.
  3. Process isolation.
  4. Time efficiency.
Show answerHide answer

Save this lesson to see this answer.

Question 2 of 10

A 16-byte heap block is freed. An old pointer is then used to write inside the same process's still-mapped heap, and no immediate fault occurs. What best describes the write?
  1. A double free because the address is reused.
  2. A valid write because the heap remains mapped.
  3. Use-after-free with undefined behavior.
  4. A leak because the block was never released.
Show answerHide answer

Save this lesson to see this answer.

Question 3 of 10

In a segmentation model, a heap occupies physical bytes 10,000 through 13,999. Its next 1,000 physical bytes are busy. Free holes elsewhere are 3,000 and 4,500 bytes. The allocator needs to grow this heap to 5,000 bytes. Can direct extension or relocation satisfy it?
  1. Relocation works in the largest 4,500-byte hole.
  2. Neither route has a suitable contiguous extent.
  3. Direct extension works because 1,000 extra bytes are needed.
  4. Relocation works because the holes total 7,500 bytes.
Show answerHide answer

Save this lesson to see this answer.

Question 4 of 10

A size-bounds process occupies physical bytes 36,000 through 40,095. An instruction at virtual 3,900 attempts to load from virtual 4,096. What happens?
  1. The fetch succeeds at 39,900; the load faults.
  2. Both accesses fault; each exceeds the size bound.
  3. Both accesses succeed in the assigned region.
  4. The fetch succeeds at 39,900; the load uses 40,096.
Show answerHide answer

Save this lesson to see this answer.

Question 5 of 10

An OS copies a paused process from base 22,000 to base 47,000 without changing its bounds. Where should its virtual pointer 960 reach after it resumes?
  1. Physical byte 22,960.
  2. Physical byte 69,960.
  3. Physical byte 25,960.
  4. Physical byte 47,960.
Show answerHide answer

Save this lesson to see this answer.

Question 6 of 10

A 14-bit virtual address uses two selector bits and twelve offset bits. Selector 01 names an upward heap with base 52,000 and size 900. What happens to a read at virtual address 0x1380?
  1. It faults because 0x1380 exceeds size 900.
  2. It reaches physical byte 52,896.
  3. It reaches physical byte 52,900.
  4. It reaches physical byte 56,992.
Show answerHide answer

Save this lesson to see this answer.

Question 7 of 10

An OS has free holes of 5 KB, 11 KB, and 7 KB, separated by allocated segments. It must place a 13 KB segment without moving live segments. Why can the request fail?
  1. Every segment must use the same fixed-size slot.
  2. The largest existing hole is only 11 KB.
  3. The free holes provide less than 13 KB combined.
  4. The segment must use the smallest hole first.
Show answerHide answer

Save this lesson to see this answer.

Question 8 of 10

A 1,024-byte heap at 8,000 uses 16-byte allocation headers and 16-byte free nodes. Each free node records usable bytes after itself. Two 80-byte payloads are allocated from the low end. What is the remaining free node's address and usable size?
  1. Address 8,192; usable size 816 bytes.
  2. Address 8,192; usable size 832 bytes.
  3. Address 8,160; usable size 848 bytes.
  4. Address 8,224; usable size 800 bytes.
Show answerHide answer

Save this lesson to see this answer.

Question 9 of 10

A kernel repeatedly allocates the same object type, and initializing that type is expensive. Which design directly supports reuse of initialized objects?
  1. A slab object cache.
  2. A next-fit cursor.
  3. A size-bounds register.
  4. A static relocator.
Show answerHide answer

Save this lesson to see this answer.

Question 10 of 10

In a buddy region, what is the buddy offset of an 8 KB block at region-relative offset 24 KB?
  1. 8 KB
  2. 0 KB
  3. 16 KB
  4. 32 KB
Show answerHide answer

Save this lesson to see this answer.

Set 4: Explaining failures and preserving mappings10 Practice Questions

Save this lesson to see every answer and practice every set.

Question 1 of 10

Two processes each reserve a 24 KB base-and-bounds slot. Each uses 2 KB of code, 3 KB of heap, and 1 KB of stack. How much physical storage do their reserved slots consume together?
  1. 12 KB
  2. 48 KB
  3. 24 KB
  4. 36 KB
Show answerHide answer

Save this lesson to see this answer.

Question 2 of 10

A function contains a static local counter and an ordinary automatic local counter. Which counter's storage lasts across successive calls?
  1. Both of the local counters.
  2. Neither local counter.
  3. The static local counter.
  4. The automatic local counter.
Show answerHide answer

Save this lesson to see this answer.

Question 3 of 10

A C string contains 23 visible single-byte characters. A program allocates exactly 23 bytes and copies the characters followed by a null terminator. What goes wrong?
  1. The first character is an uninitialized read.
  2. The pointer needs 24 bytes of storage itself.
  3. The allocator receives an invalid free request.
  4. The terminator is written beyond the block.
Show answerHide answer

Save this lesson to see this answer.

Question 4 of 10

A 48 KB physical pool holds three processes. Each has a 16 KB virtual span but currently uses contiguous code, heap, and stack extents totaling 5 KB. A fourth identical process arrives. Ignoring metadata and fragmentation, can whole-space base and bounds and separate segmentation admit it?
  1. Base and bounds cannot; segmentation can.
  2. Both schemes can admit the fourth process.
  3. Segmentation cannot; base and bounds can.
  4. Neither scheme can admit the fourth process.
Show answerHide answer

Save this lesson to see this answer.

Question 5 of 10

An upward heap starts at virtual 8,192, with size 2,000 and physical base 40,000. What happens to a read at virtual 10,192?
  1. It reaches physical byte 50,192.
  2. It reaches physical byte 41,999.
  3. It faults at the segment's exclusive end.
  4. It reaches physical byte 42,000.
Show answerHide answer

Save this lesson to see this answer.

Question 6 of 10

An upward heap starts at virtual 4,096 and has size 1,500. Its physical base changes from 20,000 to 46,000 after relocation. A trace then shows virtual 5,300 reaching physical 51,300. What correction is needed?
  1. Use physical 47,204 after removing the virtual heap start.
  2. Use physical 21,204 by restoring the original base.
  3. Keep physical 51,300 because relocation changes the full address.
  4. Use physical 50,096 by replacing the offset with the start.
Show answerHide answer

Save this lesson to see this answer.

Question 7 of 10

A 14-bit address uses two selector bits and twelve offset bits. Selector 11 names a downward stack with physical base 70,000 and current size 1,024. Reads are allowed. What happens at virtual address 15,360?
  1. It reaches physical 73,072 by adding the positive field.
  2. It reaches the lowest stack byte, physical 68,976.
  3. It faults because the displacement magnitude equals the size.
  4. It reaches physical 68,975 as the last permitted byte.
Show answerHide answer

Save this lesson to see this answer.

Question 8 of 10

An allocator rounds every payload request to a multiple of 32 bytes and ignores headers. What kind and amount of waste does a 70-byte request create?
  1. 32 bytes of external fragmentation.
  2. 6 bytes of internal fragmentation.
  3. 26 bytes of external fragmentation.
  4. 26 bytes of internal fragmentation.
Show answerHide answer

Save this lesson to see this answer.

Question 9 of 10

A 100-byte heap has live chunks at bytes 20–39 and 60–79; all other bytes are free. The first live chunk is freed and adjacent free chunks coalesce. Ignoring metadata, can a 65-byte request then succeed?
  1. No; the largest free extent is 40 bytes.
  2. Yes; there are 80 free bytes in total.
  3. Yes; freeing one chunk joins the entire heap.
  4. No; the largest free extent is 60 bytes.
Show answerHide answer

Save this lesson to see this answer.

Question 10 of 10

Holes in address order are 26, 58, and 42 bytes. Headers are ignored. First fit and best fit each allocate 24 bytes, then 40 bytes, with no frees. Which policy can then serve a 55-byte request?
  1. Neither can serve the 55-byte request.
  2. First fit can; best fit cannot.
  3. Best fit can; first fit cannot.
  4. Both can serve the 55-byte request.
Show answerHide answer

Save this lesson to see this answer.

Set 5: Combined translation and allocation reasoning10 Practice Questions

Save this lesson to see every answer and practice every set.

Question 1 of 10

A design gives two processes one read-only physical code region and separate writable regions. Which virtualization goals can this satisfy while saving space?
  1. Transparency requires writable shared code for both.
  2. Space efficiency requires removing all access checks.
  3. Transparency and isolation can both be preserved.
  4. Isolation is preserved only by separate code copies.
Show answerHide answer

Save this lesson to see this answer.

Question 2 of 10

A segmented heap occupies physical bytes 20,000 through 23,999, followed by busy memory. Its break is virtual 10,000. The OS moves the heap to a free 6,000-byte region at physical 40,000 and successfully grants sbrk(1500). What does sbrk return, and where does the heap's first existing byte now reside?
  1. Return 11,500; existing first byte at 40,000.
  2. Return 10,000; existing first byte at 40,000.
  3. Return 41,500; existing first byte at 40,000.
  4. Return 10,000; existing first byte at 20,000.
Show answerHide answer

Save this lesson to see this answer.

Question 3 of 10

A user-mode program attempts to set its base register to the kernel's physical start. What should the processor do?
  1. Treat the requested base as an ordinary virtual pointer.
  2. Install the base and rely on the existing size check.
  3. Raise an exception for the privileged operation.
  4. Install the base only for this program's next load.
Show answerHide answer

Save this lesson to see this answer.

Question 4 of 10

A 14-bit address has two selector bits and twelve offset bits. Selector 01 is an upward heap with base 26,000 and size 1,200. Its size later grows to 1,400. How does a read at virtual 0x1500 change?
  1. It changes from a fault to physical byte 27,280.
  2. It stays legal at physical byte 27,280.
  3. It stays a fault because the selector changes.
  4. It changes from a fault to physical byte 31,376.
Show answerHide answer

Save this lesson to see this answer.

Question 5 of 10

After pausing processes and compacting their physical segments, what mapping data must the OS correct for the segments it moved?
  1. Their physical bases.
  2. Their virtual pointers.
  3. Their access rights.
  4. Their code offsets.
Show answerHide answer

Save this lesson to see this answer.

Question 6 of 10

Physical memory has live segment A at bytes 0 through 3,999, a free hole at bytes 4,000 through 5,999, live segment B at bytes 6,000 through 8,999, and a free hole at bytes 9,000 through 11,999. B may move. Where can B be moved so a new 4,500-byte segment fits afterward?
  1. Move B to bytes 5,000 through 7,999.
  2. Move B to bytes 8,000 through 10,999.
  3. Move B to bytes 7,000 through 9,999.
  4. Move B to bytes 4,000 through 6,999.
Show answerHide answer

Save this lesson to see this answer.

Question 7 of 10

A 640-byte heap begins at 24,000. Allocations have 16-byte headers and no rounding. Payloads of 64, 96, and 64 bytes are allocated consecutively from the low end. The first two are freed and coalesced. First fit then serves a 144-byte payload. What pointer and total free remainder inside that merged chunk result?
  1. Pointer 24,016; remainder 32 bytes.
  2. Pointer 24,016; remainder 48 bytes.
  3. Pointer 24,096; remainder 32 bytes.
  4. Pointer 24,000; remainder 48 bytes.
Show answerHide answer

Save this lesson to see this answer.

Question 8 of 10

Holes in address order are 36, 64, and 48 bytes. Headers are ignored. A 32-byte request arrives, then a 60-byte request. Next fit starts its first search at the second hole and resumes at that hole's remainder. Which policy can serve both requests: best fit or this next fit?
  1. Neither policy can serve both requests.
  2. Best fit can; next fit cannot.
  3. Both policies can serve both requests.
  4. Next fit can; best fit cannot.
Show answerHide answer

Save this lesson to see this answer.

Question 9 of 10

A buddy allocator ignores overhead in a 32 KB region. It allocates 7 KB at offset 0, another 7 KB at offset 8 KB, and 12 KB at offset 16 KB. Both 7 KB allocations are freed. Why can it not satisfy a new 20 KB request?
  1. The two freed allocations supply only 14 KB, so they cannot form a 16 KB block.
  2. The required 32 KB block cannot form while its upper 16 KB buddy is live.
  3. The available 16 KB block falls just 4 KB short of the required block size.
  4. The lower free blocks remain separate because buddy merging needs a new split.
Show answerHide answer

Save this lesson to see this answer.

Question 10 of 10

A base-and-bounds process has physical base 11,500. What physical address corresponds to its legal virtual address 700?
  1. 10,800
  2. 700
  3. 11,500
  4. 12,200
Show answerHide answer

Save this lesson to see this answer.

Stuck on your own question? Homework Help

Key Terms

73 Key Terms, each with its definition

A

Address space
An address space is the view of memory available to one running process, including regions for instructions, data, heap blocks, and function calls.
Two processes can use the same address-space layout while their bytes occupy different physical regions.
Allocation header
An allocation header is metadata stored before a returned payload, commonly recording size so the allocator can process a later free.
With a sixteen-byte header, a payload pointer of 8,016 leads back to metadata at 8,000.
Allocation rounding
Allocation rounding raises a requested size to a supported size or alignment, leaving any excess capacity inside the allocated chunk.
Rounding 21 bytes to a 32-byte chunk leaves 11 bytes of internal waste.
Anonymous mapping
An anonymous mapping is a zero-filled virtual memory region created without associating the region's storage with a file.
An allocator can obtain a large separate region through an anonymous mmap request.
Arena
An arena is a separately managed allocator region used alongside other arenas to reduce competition for one shared allocation lock.
Threads using different arenas can satisfy many requests without waiting for the same allocator lock.

B

Base register
A base register holds the physical starting address of a region in ordinary upward relocation, to which valid virtual offsets are added.
With physical base 12,000, virtual offset 200 reaches physical byte 12,200 after a successful check.
Best fit
Best fit selects the smallest free chunk large enough for a request, limiting the immediate leftover but sometimes creating tiny slivers.
For holes of 60, 28, and 44 bytes, a 25-byte request takes the 28-byte hole under best fit.
Bit mask
A bit mask selects chosen bit positions with a bitwise operation, allowing hardware or code to separate address fields.
Applying va & 0x0FFF keeps twelve low bits while clearing the two segment bits of a fourteen-bit address.
Bounds register
A bounds register limits a process region, holding its byte size in this model; valid virtual addresses must be strictly below that size.
Bounds 4,096 accepts virtual byte 4,095 but rejects an access at virtual address 4,096.
brk
brk sets the traditional heap's end boundary to a specified address, allowing the allocator to change the size of that region.
An allocator owns the break bookkeeping, so application code should request blocks through the library.
Buddy
A buddy is the same-size partner created by splitting one parent block, identifiable by XORing its partner's offset with the block size.
Two adjacent 8 KB blocks cannot merge unless they are the partners of one 16 KB split.
Buddy allocator
A buddy allocator manages power-of-two blocks, splitting into equal halves and merging a freed block only with its matching free buddy.
A 10 KB request receives a 16 KB block, leaving 6 KB unused inside that allocation.
Buffer overflow
A buffer overflow is a write beyond the allocated end of a buffer, which can corrupt neighboring data or allocator bookkeeping.
Copying a string into space with no byte for its null terminator can overflow the buffer.

C

calloc
calloc is a C library allocation function that supplies storage filled with zero bytes, unlike the uncleared storage returned by malloc.
A buffer obtained through calloc begins with zero bytes before the program writes any data.
Coalescing
Coalescing joins adjacent free chunks into a larger free chunk without moving live allocations, reducing separated free-list entries.
Freeing an intervening block can let two neighboring holes join into one usable allocation extent.
Coarse-grained segmentation
Coarse-grained segmentation divides an address space into a few large regions, commonly code, heap, and stack, with separate translation state.
A small group of segment register pairs can describe the classic three-region process layout.
Code sharing
Code sharing lets processes execute one physical copy of immutable instructions while keeping their writable process state separate.
Two processes can use the same read-only code base with different heap and stack bases.
Compaction
Compaction moves live physical regions together and updates their mappings to combine scattered free capacity into a larger hole.
The OS copies segments and changes their bases while programs keep using the same virtual addresses.
Context switch
A context switch replaces the running process's active CPU state with another process's saved state, including its memory translation values.
Restoring the next process's general registers without its base would leave the wrong memory view active.
Contiguous region
A contiguous region is an uninterrupted interval of neighboring byte addresses, required for a whole process under simple base and bounds.
Separate physical holes cannot jointly hold one region that must be contiguous.

D

Dangling pointer
A dangling pointer is a pointer to storage whose lifetime has ended, such as a heap block already returned to the allocator.
Reading through an old pointer after its block is freed is a use-after-free error.
Double free
A double free is an attempt to release the same allocation again after it has already been freed, violating the allocator's ownership rules.
Calling free twice through copied pointers to one block can corrupt the allocation library's state.
Dynamic relocation
Dynamic relocation translates addresses during execution, allowing the OS to move physical storage while preserving virtual pointer values.
Moving a paused process and changing its base makes its existing pointers reach the copied bytes.

E

Embedded free-list node
An embedded free-list node stores a free chunk's size and links inside the chunk itself, reusing managed memory for bookkeeping.
After a free chunk is split, its free tail's first bytes hold its node instead of a separate allocation outside the heap.
Exception handler
An exception handler is OS code entered after hardware detects an event such as an invalid memory address or a forbidden instruction.
A bounds violation transfers control to the registered handler, which usually terminates the process.
External fragmentation
External fragmentation leaves free memory in separate holes too small for a contiguous request, despite enough total free capacity.
Holes of 7 KB and 9 KB cannot hold one 12 KB segment, even though they total 16 KB.

F

Fine-grained segmentation
Fine-grained segmentation divides an address space into many smaller independently protected regions, described through a segment table.
A separate data structure can have its own sharing and access rules in a fine-grained design.
First fit
First fit chooses the first sufficient chunk in list order and stops searching, so its placement depends on how that list is ordered.
With address-ordered holes of 60, 28, and 44 bytes, a 25-byte request uses the 60-byte hole.
free
free is a C library function that returns a live allocated block to the allocator; passing NULL is allowed and has no effect.
The allocator can reuse a freed block even if the process keeps the same OS memory footprint.
Free list
A free list records available chunks and their sizes, with links or another structure that lets the allocator find and update entries.
After splitting a chunk, its unused tail stays on the free list if it can hold a usable free node.
Free-space management
Free-space management tracks available chunks and chooses where requests go, at the scale of a process heap or OS physical regions.
An allocator must find one sufficient chunk even when its free-byte total exceeds the request.

G

Growth direction
A segment's growth direction records whether its valid region extends upward from a first byte or downward from an upper boundary.
The stack's direction changes how hardware interprets the low address field before adding the base.

H

Heap
The heap is a process region used for blocks requested during execution, whose lifetimes are managed through allocation and release.
An object on the heap can outlive the function that originally requested its storage.

I

Implicit segment selection
Implicit segment selection chooses translation state from the way an address was formed, such as instruction fetch or stack-pointer use.
A fetch uses code translation without needing an explicit segment-number field in its address.
Internal fragmentation
Internal fragmentation is unused capacity inside an allocated region, caused by reserving more space than its useful contents require.
A 16 KB process slot holding 4 KB of useful contents wastes 12 KB inside its allocation.
Isolation
Isolation is the separation enforced between processes so an unauthorized access cannot read or corrupt another process or the kernel.
Hardware rejects an editor's access outside its allowed region before it damages a neighboring process.

L

Live allocation
A live allocation is a block still owned by the program and not yet freed, whose returned address an ordinary C allocator must preserve.
A live block between free holes prevents the allocator from coalescing those holes across it.
Lock contention
Lock contention occurs when concurrent threads wait for access to the same protected allocator state, limiting parallel allocation progress.
Local caches and multiple arenas reduce the number of allocations that need one common lock.

M

malloc
malloc is a C library function that requests a byte-sized block and returns its address, or NULL on failure, without clearing its contents.
A request for six integers uses malloc(6 * sizeof(int)) to account for the element size.
Mechanism
A mechanism is the implementation that carries out an operation, such as hardware checking bounds and adding a base on memory accesses.
Changing the hole-selection rule does not require replacing the hardware translation mechanism.
Memory leak
A memory leak occurs when allocated storage is no longer released when needed, often because the program loses its last usable pointer to it.
A function that returns without preserving or freeing its only heap pointer leaves an unreachable block.
Memory management unit
The memory management unit is processor hardware that translates virtual addresses and checks access rules using OS-installed state.
The MMU translates an instruction fetch without calling an OS routine for each instruction.
munmap
munmap removes a mapped region from a process's address space, unlike returning a small block to a library pool for reuse.
Freeing a separately mapped large allocation can let its allocator remove the underlying mapping.

N

Negative displacement
A negative displacement measures a downward segment access below its upper boundary, obtained by subtracting the full window size.
A field of 3,000 in a 4,096-byte stack window gives a displacement of −1,096.
Next fit
Next fit searches for a sufficient chunk from a saved position, wrapping through the list instead of restarting at its beginning.
Starting a next-fit search at a list's third hole instead of its first can change its choice even when the free sizes are unchanged.

O

Offset field
An offset field is the part of a segmented address that locates a byte within a selector window, before any downward-growth adjustment.
A twelve-bit field permits 4,096 positions even if the selected segment currently uses fewer bytes.

P

Payload
A payload is the part of an allocated chunk available to the program, excluding the allocator's header and other bookkeeping.
A 96-byte payload with a sixteen-byte header occupies at least 112 bytes of the managed region.
Physical address
A physical address identifies a location in memory hardware, reached after translation of a process's virtual memory access.
Two processes' virtual address 800 can translate to different physical addresses on the same machine.
Policy
A policy is a rule for choosing among possible actions, such as which free physical region should hold a newly created process.
Choosing the smallest sufficient hole is a placement policy applied by a memory manager.
Privileged instruction
A privileged instruction is an operation allowed only in kernel mode, preventing user programs from changing protected machine state.
An attempted base-register update from user mode raises an exception instead of changing the mapping.
Process control block
A process control block is an OS record holding a process's saved execution state, including translation values when the process is inactive.
The OS restores the next process's saved base and bounds from its process control block.
Program break
The program break is the virtual boundary just past the traditional heap's end, moved when that heap region is extended or reduced.
If the break is 30,000, byte 30,000 is outside the heap until the boundary moves higher.
Protection bits
Protection bits specify permitted operations on a region, such as reading, writing, or executing, checked separately from bounds.
A valid code offset still faults when the process attempts a write to read-execute storage.

R

Read-execute permission
Read-execute permission allows a region's bytes to be read and run as instructions while denying writes that would modify them.
A shared code segment permits instruction fetches but rejects an attempted store into its bytes.
realloc
realloc is a C library function that changes an allocated block's size and may move its contents to a block at a different address.
A growing buffer may move when its current block has no space available immediately after it.

S

sbrk
sbrk changes the program break by a requested byte increment and returns the old break on success; a zero increment reports the current break.
A successful sbrk(1024) at break 20,000 returns 20,000 and leaves the new break at 21,024.
Segment
A segment is a contiguous logical region of an address space with independent translation state, such as a code, heap, or stack region.
The heap segment can move without requiring the code segment to move to the same physical neighborhood.
Segment offset
A segment offset locates a byte relative to its segment's virtual origin; upward translation adds the checked offset to the physical base.
Virtual byte 5,100 in a heap starting at 4,096 has offset 1,004 before physical relocation.
Segment selector
A segment selector identifies which segment's translation state applies to an explicit virtual address, separately from its offset field.
In a fourteen-bit split, leading bits 01 can select heap while the low twelve bits locate its byte.
Segment table
A segment table stores translation and protection information for many segments, supporting more regions than a few fixed register pairs.
Fine-grained segmentation looks up each selected region's base, size, and access controls in a table.
Segmentation
Segmentation translates logical regions independently using per-segment state, allowing physical placement to differ from the virtual layout.
A 16 KB virtual space can use only 7 KB of physical backing for its three currently used segments.
Segmentation fault
A segmentation fault is a reported illegal memory access; the name persists even when the machine does not use classic segmentation.
A permission violation can produce a segmentation fault even when its offset lies inside the region.
Segregated lists
Segregated lists keep separate pools for selected block sizes so common-size requests can be served without a general search.
A pool of 64-byte chunks quickly serves repeated requests belonging to that size class.
Slab allocator
A slab allocator keeps caches of recurring object types in slabs, supporting fast object reuse and reduced repeated initialization work.
A kernel can obtain another process descriptor from its object cache instead of building a fresh one.
Sparse address space
A sparse address space has large unused virtual gaps between used regions, making whole-span physical allocation wasteful.
Separating heap and stack into independent segments avoids reserving their empty intervening gap.
Splitting
Splitting divides a free chunk into an allocated part and a remaining free part, preserving the tail for later requests.
A 24-byte request taken from an 80-byte chunk leaves 56 bytes when headers are ignored.
Stack
A stack is a region used for function-call state, including return addresses and ordinary local variables in the usual execution model.
Returning from a function releases its stack frame but does not release a heap block it allocated.
Static relocation
Static relocation rewrites addresses when loading a program to match its physical placement, without itself enforcing memory-access protection.
Changing the load location requires the loader to rewrite embedded addresses for the new position.
Static storage
Static storage is storage for globals and static local variables that lasts throughout the program's run, independent of individual calls.
A static local counter retains its value between calls instead of disappearing with each stack frame.

T

Transparency
Transparency is the property that lets a program use its own memory view without managing the physical placement or sharing behind it.
A process keeps the same virtual pointers after the OS relocates its physical memory.

U

Uninitialized read
An uninitialized read uses stored data before the program has established its value, as when it reads uncleared bytes returned by malloc.
Allocating enough space for an integer does not give that integer a meaningful initial value.

V

Virtual address
A virtual address identifies a byte in a process's memory view and is translated before the processor accesses physical memory.
A pointer printed by a C program shows a virtual address even when the OS moves its physical storage.

W

Worst fit
Worst fit selects the largest free chunk, aiming to leave a useful remainder but potentially consuming a hole needed by later large requests.
A small request placed in the only large hole can make the next larger allocation fail.

About this lesson

By StudeliReport a mistake

Make your own Study Materials

Turn your notes, slides and documents into Study Guides, Practice Questions, Flashcards and 6 more tools.

Get Started