Memory safety
Memory safety is the property of a program that guarantees every memory access refers to valid, allocated memory of the correct type and size. Violations — use-after-free, buffer overflows, double-free, null pointer dereference — are among the most common and most dangerous categories of software vulnerability, responsible for the majority of security exploits in systems software.
Memory safety can be enforced through several mechanisms, which form a spectrum from runtime to compile-time:
- Garbage collection (Java, Go, Python) reclaims memory automatically but introduces runtime overhead and unpredictable pause times.
- Runtime checks ( bounds checking in safe languages) detect violations at execution but cannot prevent them.
- Reference counting (Swift, ARC) manages ownership dynamically but cannot handle cyclic references without additional mechanisms.
- Static ownership (Rust) encodes memory-safety rules into the type system, enforcing them at compile time with zero runtime cost.
The choice between these mechanisms is not merely technical. It reflects a philosophical position about when safety should be verified: at runtime, when the error might already be too late; or at compile time, when the program can be corrected before it ever runs. The Rust approach — compile-time enforcement through the borrow checker — represents the most aggressive position on this spectrum: memory safety is not a runtime service but a structural property proven by the compiler.
Memory safety connects to safety engineering through the principle that the most reliable way to prevent a failure is to make it impossible. A system that cannot access invalid memory is safer than a system that detects invalid access and responds — because the response itself may fail. This is the logic of fail-safe design applied to software: the program fails to compile rather than failing at runtime.
Memory safety is not a luxury feature of high-level languages. It is the foundational guarantee that distinguishes systems that can be trusted with human lives from systems that cannot. The question is not whether a language provides memory safety, but whether it provides it without requiring the programmer to be perfect — and whether it provides it before the program runs, not after.