Skip to content

Commit b195ad1

Browse files
authored
Merge pull request #464 from RalfJung/allocation
define 'allocation' and 'memory address'
2 parents 7cee58a + e8e5765 commit b195ad1

File tree

1 file changed

+31
-3
lines changed

1 file changed

+31
-3
lines changed

reference/src/glossary.md

+31-3
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ For instance `#[repr(C)] struct S(i32)` is (guaranteed to be) layout-compatible
1616
[abstract byte]: #abstract-byte
1717

1818
The *byte* is the smallest unit of storage in Rust.
19-
Memory allocations are thought of as storing a list of bytes, and at the lowest level each load returns a list of bytes and each store takes a list of bytes and puts it into memory.
19+
[Memory allocations][allocation] are thought of as storing a list of bytes, and at the lowest level each load returns a list of bytes and each store takes a list of bytes and puts it into memory.
2020
(The [representation relation] then defines how to convert between those lists of bytes and higher-level values such as mathematical integers or pointers.)
2121

2222
However, a *byte* in the Rust Abstract Machine is more complicated than just an integer in `0..256` -- think of it as there being some extra "shadow state" that is relevant for the Abstract Machine execution (in particular, for whether this execution has UB), but that disappears when compiling the program to assembly.
@@ -95,6 +95,23 @@ somewhat differently from this definition. However, that's considered a low
9595
level detail of a particular Rust implementation. When programming Rust, the
9696
Abstract Rust Machine is intended to operate according to the definition here.
9797

98+
### Allocation
99+
[allocation]: #allocation
100+
101+
An *allocation* is a chunk of memory that is addressable from Rust.
102+
Allocations are created for objects on the heap, for stack-allocated variables, for globals (statics and consts), but also for objects that do not have Rust-inspectable data such as functions and vtables.
103+
An allocation has a contiguous range of [memory addresses][memory-address] that it covers, and it can generally only be deallocated all at once.
104+
(Though in the future, we might allow allocations with holes, and we might allow growing/shrinking an allocation.)
105+
This range can be empty, but even empty allocations have a *base address* that they are located at.
106+
The base address of an allocation is not necessarily unique; but if two distinct allocations have the same base address then at least one of them must be empty.
107+
108+
Pointer arithmetic is generally only possible within an allocation:
109+
[provenance][pointer-provenance] ensures that each pointer "remembers" which allocation it points to,
110+
and accesses are only permitted if the address is in range of the allocation associated with the pointer.
111+
112+
Data inside an allocation is stored as [abstract bytes][abstract-byte];
113+
in particular, allocations do not track which type the data inside them has.
114+
98115
### Interior mutability
99116

100117
*Interior Mutation* means mutating memory where there also exists a live shared reference pointing to the same memory; or mutating memory through a pointer derived from a shared reference.
@@ -119,6 +136,17 @@ Note that layout does not capture everything that there is to say about how a ty
119136
Note: Originally, *layout* and *representation* were treated as synonyms, and Rust language features like the `#[repr]` attribute reflect this.
120137
In this document, *layout* and [*representation*][representation relation] are not synonyms.
121138

139+
### Memory Address
140+
[memory address]: #memory-address
141+
142+
A *memory address* is an integer value that identifies where in the process' memory some data is stored.
143+
This will typically be a virtual address, if the Rust process runs as a regular user-space program.
144+
It can also be a physical address for bare-level / kernel code. Rust doesn't really care either way, the point is:
145+
it's an address as understood by the CPU, it's what the load/store instructions need to identify where in memory to perform the load/store.
146+
147+
Note that a pointer in Rust is *not* just a memory address.
148+
A pointer value consists of a memory address and [provenance][pointer-provenance].
149+
122150
### Niche
123151
[niche]: #niche
124152

@@ -171,7 +199,7 @@ The key operations on a place are:
171199
### Pointer Provenance
172200
[provenance]: #pointer-provenance
173201

174-
The *provenance* of a pointer is used to distinguish pointers that point to the same memory address (i.e., pointers that, when cast to `usize`, will compare equal).
202+
The *provenance* of a pointer is used to distinguish pointers that point to the same [memory address][memory-address] (i.e., pointers that, when cast to `usize`, will compare equal).
175203
Provenance is extra state that only exists in the Rust Abstract Machine; it is needed to specify program behavior but not present any more when the program runs on real hardware.
176204
In other words, pointers that only differ in their provenance can *not* be distinguished any more in the final binary (but provenance can influence how the compiler translates the program).
177205

@@ -180,7 +208,7 @@ It is also unclear whether provenance applies to more than just pointers, i.e.,
180208
In the following, we give some examples if what provenance *could* look like.
181209

182210
*Using provenance to track originating allocation.*
183-
For example, we have to distinguish pointers to the same location if they originated from different allocations.
211+
For example, we have to distinguish pointers to the same location if they originated from different [allocations][allocation].
184212
Cross-allocation pointer arithmetic [does not lead to usable pointers](https://doc.rust-lang.org/std/primitive.pointer.html#method.wrapping_offset), so the Rust Abstract Machine *somehow* has to remember the original allocation to which a pointer pointed.
185213
It could use provenance to achieve this:
186214

0 commit comments

Comments
 (0)