Course contentsShow
← Rust
Lesson 1395 of 1,91012. Unsafe Rust and Low-Level AccessFree lesson

Validating Pointer Dereferencing

You will enforce non-null and alignment checks before dereferencing raw pointers in performance-critical paths.

Validating Pointer Dereferencing

In this lesson, you’ll learn how to transform raw pointers into safe, usable references by enforcing strict non-null and alignment checks before dereferencing them in performance-critical paths.

When you work with *const T or *mut T in unsafe Rust, the compiler cannot guarantee that the address they point to is valid. Dereferencing a pointer that is null, dangling, or improperly aligned triggers Undefined Behavior (UB). While performance-critical systems often bypass the overhead of standard wrappers, skipping validation is a recipe for memory corruption.

The Validation Checklist

To safely dereference a raw pointer, you must verify three fundamental conditions:

  1. Non-nullness: The pointer must not be ptr::null().
  2. Alignment: The pointer address must be a multiple of std::mem::align_of::<T>().
  3. Initialization: The memory region must be initialized for type T.

Implementation Strategy

In high-performance paths, you should perform these checks manually before entering the unsafe block. This keeps the unsafe surface area minimal and readable.

fn safe_read_ptr<T>(ptr: *const T) -> Option<&'static T> {
    // 1. Check for null
    if ptr.is_null() {
        return None;
    }

    // 2. Check for alignment
    let alignment = std::mem::align_of::<T>();
    if (ptr as usize) % alignment != 0 {
        return None;
    }

    // 3. Perform dereference inside the smallest possible unsafe block
    unsafe {
        Some(&*ptr)
    }
}

By performing these checks at the boundary, you transform a potentially catastrophic system crash into a manageable Option type. Note that while this verifies the pointer's structure, it does not guarantee that the pointer wasn't freed elsewhere (the "dangling pointer" problem). In real-world performance-critical systems, this validation is often paired with an Arc or a manually managed custom allocator to ensure the lifetime of the underlying memory remains valid during the operation.

Always prefer creating a reference through a check rather than assuming a raw pointer’s validity based on its origin, as optimization passes can often rearrange or elide code in ways that expose subtle alignment violations.

Key Takeaway: Never dereference a raw pointer without manually verifying its alignment and non-null status to prevent memory safety violations in your high-performance code.