liveBook · Manning

Address space

As explained in Rust in Action: Systems programming concepts and techniques

An address space is the set of memory addresses available for identifying stored data and instructions in an execution environment.

An address space is a program’s way of locating data in memory. Picture its addresses as an orderly line of numbered bytes: an address identifies one byte, and a pointer uses an address to locate a value. The line is a useful model, but it is not a map of physical RAM. The operating system and CPU provide the program’s view of memory. section 6.1

See where values live

In Rust, `let b = &B` creates a reference to an array, and `println!("{:p}", b)` prints the address it points to. The location need not be known before the program runs. Try printing addresses for a global, a local variable, and boxed values: their addresses may be far apart even when the program uses little memory. section 6.2 section 6.4.2

Figure 6.3 An illustrative address space of the program provided in listing 6.1. It provides an illustration of the relationship between addresses (typically written in hexadecimal) and integers (typically written in decimal). White cells represent unused memory.

The small, imaginary address space makes the byte-by-byte layout visible. Read the hexadecimal addresses as positions in one shared space, including its unused cells. section 6.2

A process has its own virtual address space. The operating system manages mappings from virtual memory to real memory with page tables, while the CPU’s memory-management unit translates addresses. Memory is handled in pages rather than by keeping a separate mapping for every variable. This lets the operating system move inactive pages to disk or share physical pages while a program still sees its own addresses. section 6.4.1 section 6.4.3 section 10.5

A large range of possible addresses does not mean every address can be read. Trying to scan arbitrary addresses byte by byte can access an illegal location and end the program. To explore safely, first inspect known values’ addresses; for a fuller map of memory regions, ask the operating system rather than dereferencing every possible pointer. section 6.4.2 section 6.4.4

Listing 6.14 Printing the address of variables within a program
static GLOBAL: i32 = 1000;             #1
 
fn noop() -> *const i32 {
    let noop_local = 12345;            #2
    &noop_local as *const i32          #3
}
 
fn main() {
    let local_str = "a";               #4
    let local_int = 123;               #4
    let boxed_str = Box::new('b');     #4
    let boxed_int = Box::new(789);     #4
    let fn_int = noop();               #4
 
    println!("GLOBAL:    {:p}", &GLOBAL as *const i32);
    println!("local_str: {:p}", local_str as *const str);
    println!("local_int: {:p}", &local_int as *const i32);
    println!("boxed_int: {:p}", Box::into_raw(boxed_int));
    println!("boxed_str: {:p}", Box::into_raw(boxed_str));
    println!("fn_int:    {:p}", fn_int);}

Run the Rust example to print addresses of global, local, and boxed values. Compare the resulting clusters instead of expecting every value to sit next to every other one. section 6.4.2

An address space can also be used as an isolation boundary. Separate processes have their own virtual address spaces. WebAssembly adds another boundary inside a process: a module accesses its linear memory without seeing the process’s other memory addresses. section 10.5 section 10.5.4

How Rust in Action: Systems programming concepts and techniques covers it

How deep it goes
Works from a byte-address model through virtual-memory terminology and hands-on inspection, while treating OS–CPU implementation details as a general guide.
Examples
Uses printed Rust pointer addresses, an illustrative 49-byte layout, failed byte-by-byte scans, and Windows memory-region inspection.
What it assumes
Introduces pointers through Rust references and defines virtual-memory terms before using them to inspect memory.
What you can do after
Apply it via the Windows API to inspect a process’s memory regions without blindly dereferencing addresses.
How it connects
Connects address spaces to pointers, virtual memory, paging, processes, and WebAssembly linear memory.

Also explained in

Compare how 3 books explain address space →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Rust in Action: Systems programming concepts and techniques. The section links point to the parts of the book it draws on.