AlgoMaster Logo

Logical and Physical Memory

21 min readUpdated August 7, 2026
Listen to this chapter
Unlock Audio

A service crashes and logs the address of an invalid access:

It is tempting to read this as a location in the machine's RAM. It is not. The value is an address inside that service process's memory view. Another process can use the same number for unrelated data, and the bytes may be stored at a completely different location in physical memory.

Operating systems separate these two address namespaces:

  • A logical address is the address generated and used while a process executes.
  • A physical address identifies a location in the machine's physical address space, including locations used to reach RAM.

In modern general-purpose systems, a logical address is commonly called a virtual address. This course uses logical address and virtual address interchangeably when discussing a process.

Programs operate on logical addresses. The operating system and hardware cooperate to connect valid logical addresses to physical memory.

This separation is what lets every process have a private address space, lets programs run without knowing where their bytes sit in RAM, and allows controlled sharing without exposing machine-wide memory addresses to application code.

Two Address Namespaces

An address is a number that names a byte-sized location within some address namespace. The namespace determines what the number means.

For a running process, an instruction might read from logical address:

That number is interpreted using the current process's address-space context. It might identify a local variable on one thread's stack.

The memory system eventually needs a machine-wide location from which to obtain the bytes. That location is described by a physical address. The process does not normally see this physical value, store it in its pointer variables, or need to know when it changes.

The distinction can be summarized as follows:

PropertyLogical addressPhysical address
NamespaceOne process's address spaceMachine-wide physical address space
Seen by ordinary application codeYes, as pointers and instruction addressesNormally no
Same number can mean different storage in different processesYesNo, not at one instant
Controlled byProcess layout and mappingsOperating system, hardware, and platform layout
Main purposeGive a process a stable, isolated memory viewIdentify the actual system location used for access

The physical address space is not always identical to “all installed RAM in one uninterrupted block.” Platforms can reserve physical ranges for firmware, devices, or hardware-specific purposes. In this chapter, physical memory refers mainly to the RAM portions of that machine-wide space.

Logical Addresses in Pointers

Consider an ordinary C program:

The two values printed by %p are logical addresses in this process. The same is true of:

  • A stack pointer held in a CPU register
  • A function pointer
  • A pointer returned by a memory allocator
  • An address displayed by a debugger
  • An address range shown in /proc/<pid>/maps

None of these values directly tells the application which RAM chip, module, or physical address currently holds the bytes.

This is an important debugging rule:

A pointer from an application log belongs to that process's logical address space.

To interpret the pointer, first compare it with that process's mappings and symbols. Treating the number as a machine-wide RAM offset leads to the wrong mental model.

Conceptual Translation During an Access

Suppose a CPU instruction needs to read a variable. The instruction calculates a logical address. Before the memory access can complete, the system must determine whether that address is valid for the current process and, if so, which physical location supplies the bytes.

This diagram deliberately treats translation as one conceptual step. The essential relationship is:

A logical address combined with the current process context resolves to a physical address.

The current process context matters as much as the numeric address. Changing the active process changes how logical addresses are interpreted.

Translation also checks the access against the region's permissions. A logical address may identify a valid read-only region, yet a write to that address must still be rejected.

If no valid mapping covers the address, there is no ordinary physical memory location that the process is allowed to access through it. On Linux, the resulting fault commonly causes the process to receive SIGSEGV.

One Logical Address Across Physical Locations

Suppose two worker processes run the same service executable. Both can have a variable named request_count at logical address 0x6000.

The mappings might conceptually look like this:

The same logical address appears in both processes and reaches different physical memory holding different values.

Process A reads 120, while Process B reads 7. The equal logical address does not create sharing because each translation uses a different process context.

This provides isolation without requiring programs to coordinate their pointer values. Thousands of processes can each use familiar-looking stack, code, and dynamic-memory addresses while remaining independent.

It also explains what changes during a process switch. When the CPU begins executing a thread from another process, the active address-space context changes. A later reference to the same logical number can therefore reach different memory. Threads in one process keep the same address-space context and consequently share the process's mappings.

Logical-Address Aliasing to Physical Memory

The relationship also works in the other direction. Two logical addresses can intentionally refer to the same physical storage.

For example:

Two different logical addresses reach the same physical memory, which is how processes share a region without agreeing on an address.

The logical addresses differ because each process chooses its own available range. The physical location is shared, so both processes can observe the same underlying bytes according to their permissions.

This pattern supports shared memory and shared read-only program code. One process might receive a writable view while another receives a read-only view. The physical storage can be common even though the logical addresses and access rights differ.

This means logical-to-physical relationships are not inherently one-to-one:

  • One logical number can identify different physical locations in different processes.
  • Different logical numbers can identify the same physical location.
  • An unmapped logical address identifies no accessible physical location for that process.
  • The system can change a mapping's physical placement while preserving the logical address seen by the process.

Application code should therefore depend on the logical memory contract, not on an assumed permanent physical location.

Loading simulation...

Why the Separation Exists

If programs used physical addresses directly, every executable would have to know where it could fit in the machine's current RAM layout.

Suppose two programs were both built to use physical address 0x10000 for writable data. They could not run safely at the same time without modifying at least one program's addresses. Starting and stopping other processes would continually change which physical ranges were available.

Logical addresses remove that global coordination problem. Each process gets its own namespace, while the operating system decides where the corresponding data belongs physically.

Isolation

A process can only access physical memory reachable through its own permitted mappings. Knowing another process's pointer value is not enough to access that process's data.

Relocation

A program can run even when its physical storage is not at one predetermined machine-wide address. The logical addresses used by the process remain independent of current RAM placement.

Controlled sharing

The operating system can connect selected logical ranges from multiple processes to common physical storage without exposing every other region.

Sparse layouts

A process can have widely separated code, dynamic memory, libraries, and stacks without occupying physical RAM for every numeric address between them.

Stable pointers

The operating system can manage physical placement while preserving the logical addresses stored in registers, stacks, and application data. Moving physical storage does not require searching through the program and rewriting every pointer.

The separation is therefore not an unnecessary layer. It is what makes safe multiprogramming practical.

When Does an Address Become Bound?

Address binding is the act of associating a program's memory references with actual memory locations.

The binding can happen at different times, depending on the system design.

Compile-time binding

If the final memory location is known when the program is built, the compiler and linker can produce absolute addresses.

If the program must move to another location, it generally needs to be rebuilt with different addresses. This model can work in small embedded systems where one fixed program owns a known memory layout, but it is too rigid for a general-purpose operating system running many changing processes.

In a system with no runtime translation, logical and physical address values can be identical under compile-time binding.

Load-time binding

The build tools can instead produce relocatable code. The loader chooses a location when the program starts and adjusts address-dependent references before execution begins.

The program is built without one fixed location, the loader selects an available location, and references are adjusted for it.

If the program later has to move in a system that relies only on load-time binding, those references must be adjusted again.

In a system with load-time binding but no runtime translation, the adjusted addresses used during execution directly identify physical locations.

Execution-time binding

With execution-time binding, the running program continues to generate logical addresses. Translation connects each memory access to physical memory while the program executes.

The physical association can therefore change without changing the logical pointer stored by the program. This is the model used by modern general-purpose operating systems.

These strategies describe where logical references become associated with physical memory. Modern program startup can involve several forms of relocation at once: a linker organizes an executable, a loader chooses a logical placement and adjusts some references, and runtime translation independently connects that logical layout to physical memory.

Loader relocation and runtime address translation solve related but different problems:

Confusing these two operations makes it seem as though the loader must assign one permanent RAM address to every program object. It does not.

Logical Address Space Size

The logical address space is the range of addresses a process can potentially name. Its theoretical size is related to the number of address bits available to the program.

With 32-bit addresses, there are at most:

That is a limit on the address namespace, not a promise that all 4 GiB are mapped or usable. The operating system may reserve part of the range, and individual processes usually contain unmapped gaps.

With 64-bit addresses, the mathematical range is:

Current processors and operating systems generally implement only a subset of that theoretical range. Even that subset is far larger than the memory needs of most processes.

A 64-bit pointer does not imply that the computer contains 16 EiB of RAM. Pointer width describes how addresses are represented. Installed physical memory is a separate machine resource.

This independence allows a machine with 16 GiB of RAM to run many 64-bit processes, each with its own large and mostly sparse logical address space.

Physical Address Space Size

The physical address space is the set of addresses the hardware platform can use to identify system locations. Its size depends on the implemented physical address width, not on the pointer size used by a process.

A processor may support fewer physical address bits than logical address bits. For example, a system can run 64-bit programs while implementing a much smaller physical address range.

Installed RAM can be smaller still. A platform might support a large maximum physical address space but have only a fraction populated with memory modules.

These three quantities must not be treated as synonyms:

The platform can also contain holes and reserved ranges in its physical address map. Consequently, “8 GiB of installed RAM” does not necessarily mean that every physical address from zero through exactly 8 GiB is ordinary RAM.

Ordinary application code is intentionally insulated from these platform details. They matter to the kernel, firmware, and device-management code, but a backend service should not encode assumptions about them.

Logical Address Range vs. RAM Usage

Creating or reserving a large logical range does not prove that the process owns an equally large, private, contiguous region of physical RAM.

Several facts break that simple one-to-one interpretation:

  • Logical address spaces contain unmapped gaps.
  • Some mapped storage can be shared by multiple processes.
  • Physical backing does not have to be contiguous just because the logical range is contiguous.
  • The system need not commit a unique physical byte for every possible logical address.

For example, a process might receive a large contiguous logical range:

This tells the process that the addresses form one continuous usable view. It does not reveal the physical locations behind that view or prove that 1 GiB of RAM became active immediately.

The reverse is also possible: several logical mappings can refer to common physical storage, so adding their logical sizes would count the same underlying bytes more than once.

Address-range size and physical memory consumption are therefore different measurements.

Why Raw Pointers Do Not Cross Process Boundaries

Suppose Process A maps a shared region beginning at logical address 0x70000000. It places an object 256 bytes into that region:

Process B maps the same shared storage at 0x52000000. If Process A stores the raw pointer 0x70000100 in the shared data, Process B cannot safely dereference it. In Process B, that logical number may be unmapped or may identify unrelated private memory.

The portable representation is the object's offset from the region's beginning:

Each process combines that offset with its own logical base:

Both logical addresses can reach the same shared physical bytes.

This is why shared-memory formats commonly use offsets, indexes, or IDs instead of process-local pointers. The same principle applies more strongly across machines: a pointer from one server's logical address space has no useful meaning on another server.

What Memory Tools Actually Show

Linux tools report information from different namespaces. Reading them correctly requires knowing which namespace each value belongs to.

Process maps show logical addresses

Display the shell's mappings:

A line may begin with:

Both ends of the range are logical addresses in that shell process. The line does not reveal the physical location of those bytes.

Debuggers, stack traces, crash dumps, and profilers also normally report logical instruction and data addresses. Symbols can be matched against these addresses because symbols belong to the program's logical layout.

System memory totals describe physical capacity

Display the kernel's RAM summary:

These values describe system memory capacity and availability. They are not upper bounds on the numeric pointer values a process can print.

A process can print a logical address numerically much larger than the installed RAM size because the pointer is a name in a sparse logical namespace, not a byte offset from the beginning of RAM.

The physical map is system-wide

Linux exposes a platform-oriented physical resource map through /proc/iomem:

Depending on permissions and environment, address values may be hidden or the view may be incomplete. Entries can describe System RAM, reserved areas, and device-related ranges.

This file is a system-wide physical map. It is not a lookup table from an application pointer to its current physical location. Ordinary process debugging should begin with the process's logical mappings instead.

Address Translation and Pointer Validity

Logical addressing gives a process a flexible memory view, but it does not permit arbitrary addresses.

For a memory access to succeed, the logical range must be mapped and the attempted operation must be allowed. A read from an unmapped address fails. A write to a read-only logical region also fails even if the region has valid physical storage behind it.

Consider:

The cast creates a pointer value; it does not create a mapping. Unless the process already has a writable region covering that address, the store is invalid.

The number 0x1234 also does not mean “write to byte 0x1234 of RAM.” It remains a process-relative logical address and must pass through the current process's memory mapping.

Conversely, translation and permission checks do not enforce all programming-language rules. An out-of-bounds pointer can still land inside a writable mapped region. The operating system may allow the store even though it corrupts another object.

Summary

A logical, or virtual, address belongs to a process's private address namespace. Application pointers, instruction addresses, debugger output, and /proc/<pid>/maps all use logical addresses. A physical address belongs to the machine-wide physical address space and identifies the system location used to reach RAM or another physical resource.

The relationship is flexible rather than one-to-one. Equal logical addresses in different processes can reach different physical memory, while different logical addresses can intentionally reach the same physical storage. This separation provides isolation, relocation, controlled sharing, sparse layouts, and stable application pointers.

Compile-time, load-time, and execution-time binding describe when memory references become associated with locations. Modern general-purpose systems rely on execution-time translation, allowing programs to operate on logical addresses without depending on physical placement.

Logical address-space size, implemented physical address-space size, and installed RAM capacity are separate quantities. A pointer value or mapped range describes the process's view; it is not a direct measurement of physical memory consumption.

Quiz

Logical and Physical Memory Quiz

5 quizzes