05 — Memory Debugging
Technical Overview
Memory errors are among the most dangerous software bugs: they produce undefined behavior, can silently corrupt data, and often manifest far from their source. A use-after-free bug may trigger a crash hours or days after the actual error occurred. A heap buffer overflow may corrupt an adjacent allocation and crash in seemingly unrelated code. Memory errors in the Linux kernel can compromise the entire system's security and stability.
The tools for catching memory errors operate at different levels of completeness and overhead: Valgrind catches all heap errors but with 20x slowdown; AddressSanitizer (ASAN) catches most errors with 2x slowdown at compile time; KASAN brings similar analysis to the kernel; and KFENCE provides probabilistic detection at production-safe overhead. Understanding when and how to deploy each is the practice.
Prerequisites
- C/C++ programming and memory allocation fundamentals (
malloc,free,new,delete) - Understanding of virtual memory and the heap
- Familiarity with compiler flags and build systems
- Linux kernel concepts for the kernel-focused sections
Core Content
Memory Error Classes
MEMORY ERROR TAXONOMY
Heap Errors Stack Errors Global/Static
┌─────────────────────────┐ ┌─────────────────────┐ ┌────────────────────┐
│ Buffer overflow │ │ Stack buffer │ │ Global buffer │
│ - Past end of alloc │ │ overflow │ │ overflow │
│ - Before start (under- │ │ │ │ │
│ flow) │ │ Stack use-after- │ │ Global use-after- │
│ │ │ return (pointer to │ │ scope (rare) │
│ Use-after-free (UAF) │ │ local var returned) │ │ │
│ - Dangling pointer │ └─────────────────────┘ └────────────────────┘
│ - Temporal safety │
│ │ Initialization Errors
│ Double-free │ ┌─────────────────────┐
│ - freeing same ptr 2x │ │ Uninitialized read │
│ │ │ (uses garbage value)│
│ Invalid free │ │ │
│ - free() non-heap ptr │ │ Uninitialized heap │
│ │ │ (malloc without │
│ Memory leak │ │ memset/calloc) │
│ - alloc without free │ └─────────────────────┘
└─────────────────────────┘
Valgrind Memcheck
Valgrind is a binary instrumentation framework. Memcheck, its default tool, instruments every memory access in the program (without source recompilation) to detect heap errors.
# Install
apt install valgrind
# Basic usage
valgrind --tool=memcheck ./myprogram arg1 arg2
# Full error detail (track origins)
valgrind --tool=memcheck \
--leak-check=full \
--show-leak-kinds=all \
--track-origins=yes \
--verbose \
./myprogram 2>&1 | tee valgrind.log
# Suppress known benign errors (e.g., in third-party libs)
valgrind --suppressions=/path/to/my.supp ./myprogram
Valgrind memcheck output examples:
# Invalid read (use-after-free):
==12345== Invalid read of size 8
==12345== at 0x401234: process_request (server.c:145)
==12345== by 0x401890: handle_connection (server.c:302)
==12345== by 0x402345: main (server.c:512)
==12345== Address 0x5204e80 is 0 bytes inside a block of size 64 free'd
==12345== at 0x4C3123A: free (in /usr/lib/valgrind/vgpreload_memcheck.so)
==12345== by 0x401567: cleanup_request (server.c:189) ← freed here
==12345== by 0x401234: process_request (server.c:133)
==12345== Block was alloc'd at
==12345== at 0x4C312BF: malloc (in /usr/lib/valgrind/vgpreload_memcheck.so)
==12345== by 0x401123: create_request (server.c:98) ← allocated here
# Memory leak summary:
==12345== LEAK SUMMARY:
==12345== definitely lost: 1,024 bytes in 8 blocks ← confirmed leaks
==12345== indirectly lost: 2,048 bytes in 16 blocks ← lost via pointer in lost block
==12345== possibly lost: 512 bytes in 4 blocks ← may or may not be leaked
==12345== still reachable: 65,536 bytes in 128 blocks ← accessible at exit (not necessarily leaked)
==12345== suppressed: 0 bytes in 0 blocks
Valgrind overhead: ~20x slowdown. Allocates ~20x more memory (shadow memory). Not suitable for production, but the only tool that catches errors in already-compiled third-party binaries without source access.
Valgrind for specific analysis:
# Memory heap profile with Massif
valgrind --tool=massif ./myprogram
ms_print massif.out.12345 | head -50
# Cache simulation with Cachegrind
valgrind --tool=cachegrind ./myprogram
cg_annotate cachegrind.out.12345 | head -100
# Thread error detection with Helgrind
valgrind --tool=helgrind ./myprogram
AddressSanitizer (ASAN)
ASAN is a compiler-based memory error detector (Serebryany et al., Google, 2012). It instruments memory accesses at compile time to detect errors at runtime. Key advantage over Valgrind: 2x overhead instead of 20x, making it usable for integration tests and CI.
ASAN uses shadow memory: for every 8 bytes of application memory, 1 byte of shadow memory tracks the state (accessible, freed, red-zone). On x86-64, shadow memory occupies the high 1/8 of the virtual address space.
ASAN SHADOW MEMORY MAP (x86-64)
Application Memory Shadow Memory (1 byte per 8 app bytes)
┌────────────────────┐ ┌─────────────────────┐
│ 0x000000000000 │ │ 0x7fff8000000000 │
│ [heap] │ ──→ │ shadow(heap) │
│ [stack] │ ──→ │ shadow(stack) │
│ [globals] │ ──→ │ shadow(globals) │
│ 0x7fffffffffff │ │ 0x7fffffffffff │
└────────────────────┘ └─────────────────────┘
Shadow byte values:
0x00: all 8 bytes accessible
0xFx: first N bytes accessible (partial, end of allocation)
0xFD: heap freed ("use-after-free" marker)
0xF1: stack left red-zone
0xF3: stack right red-zone
0xFA: heap left red-zone
0xFB: heap right red-zone
Building with ASAN:
# GCC or Clang
gcc -fsanitize=address -fno-omit-frame-pointer -g \
-o myprogram myprogram.c
# With additional sanitizers
gcc -fsanitize=address,undefined \ # ASAN + UndefinedBehaviorSanitizer
-fsanitize-address-use-after-scope \ # detect use-after-scope (stack UAF)
-fno-omit-frame-pointer \
-g -o myprogram myprogram.c
# For CMake projects:
cmake -DCMAKE_C_FLAGS="-fsanitize=address -fno-omit-frame-pointer -g" \
-DCMAKE_CXX_FLAGS="-fsanitize=address -fno-omit-frame-pointer -g" \
..
ASAN output examples:
=================================================================
==12345==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60200000eff8
READ of size 8 at 0x60200000eff8 thread T0
#0 0x401234 in process_data server.c:145
#1 0x401890 in handle_request server.c:302
#2 0x402345 in main server.c:512
0x60200000eff8 is located 0 bytes to the right of 64-byte region [0x60200000efb8,0x60200000eff8)
allocated by thread T0 here:
#0 0x7f1234567890 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.6+...)
#1 0x401123 in create_buffer server.c:98
SUMMARY: AddressSanitizer: heap-buffer-overflow server.c:145 in process_data
# Use-after-free:
==12345==ERROR: AddressSanitizer: heap-use-after-free on address 0x602000000020
WRITE of size 4 at 0x602000000020 thread T0
#0 0x401234 in use_object server.c:234
0x602000000020 is located 0 bytes inside of 64-byte region [0x602000000020,0x602000000060)
freed by thread T0 here:
#0 0x7f1234 in free (...asan.so.6+...)
#1 0x401567 in destroy_object server.c:178
# Double-free:
==12345==ERROR: AddressSanitizer: attempting double-free on 0x602000000020
ASAN runtime options (via ASAN_OPTIONS environment variable):
# Get full leak report at program exit (LeakSanitizer integrated with ASAN)
ASAN_OPTIONS=detect_leaks=1 ./myprogram
# Abort on first error (default) vs continue
ASAN_OPTIONS=halt_on_error=0 ./myprogram
# Write report to file instead of stderr
ASAN_OPTIONS=log_path=/tmp/asan_report.txt ./myprogram
# Combined options
ASAN_OPTIONS=detect_leaks=1:halt_on_error=0:log_path=/tmp/asan.log ./myprogram
LeakSanitizer (LSan)
LSan detects memory leaks. It is integrated with ASAN when detect_leaks=1 (default on Linux). It can also run standalone:
# Standalone LeakSanitizer (lower overhead than full ASAN)
clang -fsanitize=leak -g -o myprogram myprogram.c
./myprogram
# Output:
# ==12345==ERROR: LeakSanitizer: detected memory leaks
# Direct leak of 1024 byte(s) in 8 object(s) allocated from:
# #0 0x... in malloc
# #1 0x401123 in init_cache server.c:45
# #2 0x401234 in main server.c:512
# SUMMARY: LeakSanitizer: 1024 byte(s) leaked in 8 allocation(s).
KASAN: Kernel AddressSanitizer
KASAN applies the same shadow memory technique to the Linux kernel, detecting heap and stack memory errors in kernel code. Enabled with CONFIG_KASAN=y and suboptions:
CONFIG_KASAN_GENERIC: full shadow memory (8:1 ratio), highest overhead (~2x memory, ~2x CPU)CONFIG_KASAN_SW_TAGS: reduced overhead using 8-bit memory tags (ARM64 only)CONFIG_KASAN_HW_TAGS: hardware-assisted memory tagging (ARMv8.5-A MTE, ~0% overhead)
# Check if KASAN is active
cat /proc/sys/kernel/kasan_multi_shot # if file exists, KASAN is compiled in
dmesg | grep "KernelAddressSanitizer"
# KASAN report in dmesg:
# BUG: KASAN: use-after-free in my_driver_write+0x78/0x1a0 [mydriver]
# Write of size 8 at addr ffff888012345678 by task systemd/1
#
# CPU: 3 PID: 1 Comm: systemd Tainted: G B 5.15.0 #1
#
# Call trace:
# dump_stack+0x64/0x7c
# print_report+0xb1/0x2a0
# kasan_report+0xab/0xf0
# my_driver_write+0x78/0x1a0 [mydriver]
# vfs_write+0xb1/0x290
# ...
#
# Allocated by task 1234:
# kasan_save_stack+0x1c/0x40
# __kasan_slab_alloc+0x5c/0x70
# kmem_cache_alloc+0x154/0x370
# my_driver_alloc+0x40/0x80 [mydriver]
#
# Freed by task 1234:
# kasan_save_stack+0x1c/0x40
# kasan_set_free_info+0x24/0x40
# __kasan_slab_free+0x8c/0xa0
# kfree+0x94/0x390
# my_driver_free+0x30/0x50 [mydriver]
KASAN is used in kernel CI (linux kernel test robot, syzbot) to automatically detect memory errors in submitted patches. Not for production due to overhead.
KFENCE: Kernel Electric Fence
KFENCE is a production-safe probabilistic memory error detector for the kernel, introduced in Linux 5.12. Unlike KASAN (which protects all allocations), KFENCE randomly selects a small percentage of allocations to place in "fenced" memory regions — guard pages surrounding the allocation.
KFENCE mechanism:
- A reserved pool of special memory pages (configurable, default 2MB)
- Periodically (default: every kfence.sample_interval = 100ms), one allocation is served from the KFENCE pool instead of the normal slab
- The allocation is surrounded by guard pages (read/write access triggers a page fault, caught by KFENCE)
- On page fault, KFENCE logs the error and the stack traces
# Check KFENCE status
cat /sys/kernel/debug/kfence/stats
# Output:
# total allocs: 12345678
# total frees: 12345670
# currently guarded: 128
# total errors: 5
# skipped: 0
# Recent KFENCE errors
dmesg | grep -A 20 "KFENCE:"
# Example KFENCE report:
# [ 1234.567] BUG: KFENCE: use-after-free in my_driver_callback+0x40/0x80 [mydriver]
# [ 1234.567] Use-after-free read at 0x0000000039b27f6e (in kfence-#47):
# [ 1234.567] my_driver_callback+0x40/0x80 [mydriver]
# [ 1234.567] timer_handler+0x54/0xc0
# [ 1234.567] call_timer_fn+0x28/0x120
# [ 1234.567] run_timer_softirq+0x3c0/0x4a0
# ...
# [ 1234.567] Object allocated by task 45:
# [ 1234.567] kmalloc+0x1c/0x30
# [ 1234.567] my_driver_init_object+0x30/0x80 [mydriver]
# [ 1234.567] Object freed by task 45:
# [ 1234.567] kfree+0x20/0x30
# [ 1234.567] my_driver_cleanup+0x60/0x80 [mydriver]
KFENCE tuning:
# Increase sampling rate (more detections, more memory)
echo 10 > /sys/module/kfence/parameters/sample_interval # every 10ms (default 100ms)
# Increase pool size (more concurrent guarded allocations)
# CONFIG_KFENCE_NUM_OBJECTS=255 (kernel config, rebuild required)
# Disable KFENCE temporarily
echo 0 > /sys/module/kfence/parameters/sample_interval
Valgrind vs ASAN Comparison
| Feature | Valgrind Memcheck | ASAN |
|---|---|---|
| Overhead | 20x CPU, 20x memory | 2x CPU, 2x memory |
| Compilation required | No (binary instrumentation) | Yes (compiler flags) |
| Heap buffer overflow | Yes | Yes |
| Heap use-after-free | Yes | Yes |
| Stack buffer overflow | Partial | Yes |
| Global buffer overflow | No | Yes |
| Uninitialized read | Yes (MemcheckOnly) | No (need MSan) |
| Memory leaks | Yes | Yes (via LSan) |
| Thread races | Separate tool (Helgrind) | No (need TSan) |
| Works with stripped binaries | Yes | No |
| Suitable for CI | Slow CI tests | Yes (fast enough) |
| Production safe | No | No |
Heap Profiling: massif and heaptrack
For diagnosing memory growth (not errors, but steady increase):
# Valgrind Massif: heap profiler
valgrind --tool=massif --pages-as-heap=yes \
--heap-admin=16 \
--threshold=1.0 \
./myprogram
# Visualize
ms_print massif.out.12345 > massif_output.txt
# heaptrack: faster Massif alternative
apt install heaptrack heaptrack-gui
heaptrack ./myprogram
heaptrack_print heaptrack.myprogram.12345.gz | head -100
heaptrack_gui heaptrack.myprogram.12345.gz # graphical view
/proc/PID/maps and /proc/PID/smaps
For live memory analysis of a running process:
# Memory map of a process
cat /proc/12345/maps
# Output:
# 00400000-00401000 r-xp 00000000 08:01 12345 /usr/bin/myprogram (text)
# 00601000-00602000 r--p 00001000 08:01 12345 /usr/bin/myprogram (read-only data)
# 00602000-00603000 rw-p 00002000 08:01 12345 /usr/bin/myprogram (read-write data)
# 00603000-01b56000 rw-p 00000000 00:00 0 [heap]
# 7f1234567000-7f1234589000 r-xp ... /lib/x86_64-linux-gnu/libc.so.6
# 7ffff7fff000-7ffff8000000 rw-p 00000000 00:00 0 [stack]
# Detailed memory stats per region (smaps)
cat /proc/12345/smaps | head -30
# 00603000-01b56000 rw-p 00000000 00:00 0 [heap]
# Size: 29132 kB (virtual size)
# KernelPageSize: 4 kB
# MMUPageSize: 4 kB
# Rss: 18432 kB (resident: actually in RAM)
# Pss: 18432 kB (proportional: shared pages / number of mappings)
# Shared_Clean: 0 kB
# Shared_Dirty: 0 kB
# Private_Clean: 0 kB
# Private_Dirty: 18432 kB (dirty pages: modified, need writeback)
# Referenced: 18432 kB
# Anonymous: 18432 kB
# LazyFree: 0 kB
# AnonHugePages: 0 kB
# ShmemPmdMapped: 0 kB
# FilePmdMapped: 0 kB
# Shared_Hugetlb: 0 kB
# Private_Hugetlb: 0 kB
# Swap: 0 kB
# SwapPss: 0 kB
# Locked: 0 kB
# Total RSS for a process
awk '/^Rss/{sum += $2} END{print sum" kB"}' /proc/12345/smaps
# smaps_rollup: summary per process (kernel 4.14+)
cat /proc/12345/smaps_rollup
Historical Context
Memory error detection has a long history. Electric Fence (Bruce Perens, 1993) was an early malloc replacement that placed allocations adjacent to guard pages — the conceptual ancestor of KFENCE. Purify (Reed Hastings, 1992 at Pure Software) was the first commercial binary-instrumentation memory error detector, predating Valgrind.
Valgrind was created by Julian Seward (then at Cambridge) in 2000, originally as a Memcheck for x86-Linux. It became the standard tool for C/C++ memory debugging through the 2000s. The architectural decision to use binary instrumentation (no recompilation needed) made it the only option for debugging closed-source binaries or already-compiled programs.
AddressSanitizer was published at USENIX ATC 2012 by Serebryany, Bruening, Potapenko, and Vyukov at Google. The key insight was that compiler instrumentation could provide 10x better performance than binary instrumentation by operating on source-level semantics. Google deployed ASAN in all internal builds; it found thousands of security-critical bugs. LLVM/Clang adopted it the same year; GCC adopted it in GCC 4.8 (2013).
KASAN for the Linux kernel (Andrey Ryabinin, 2015) and KFENCE (Alexander Potapenko, Marco Elver, Google, 2021) brought these techniques to the kernel. Google's syzbot (kernel fuzzer) uses KASAN extensively to find kernel bugs from fuzz-generated inputs.
Production Examples
# CI: run tests under ASAN (as part of build pipeline)
# CMakeLists.txt option:
# cmake -DCMAKE_C_FLAGS="-fsanitize=address,undefined -fno-omit-frame-pointer -g" .
# Production leak investigation: check /proc/PID/status
watch -n 5 'cat /proc/$(pgrep myservice)/status | grep VmRSS'
# If VmRSS grows continuously: memory leak
# Heap analysis via smaps
python3 - <<'EOF'
import re
with open('/proc/12345/smaps') as f:
heap_rss = 0
in_heap = False
for line in f:
if '[heap]' in line:
in_heap = True
if in_heap and line.startswith('Rss:'):
heap_rss += int(line.split()[1])
in_heap = False
print(f"Heap RSS: {heap_rss} kB")
EOF
# Deploy KFENCE on production to catch kernel memory errors
# (already compiled in most distribution kernels 5.12+)
# Check it's enabled:
dmesg | grep -i kfence
# KFENCE: initialized - using 4096 pages, sampling interval 100ms
Debugging Notes
ASAN false positive from third-party library: Some libraries (OpenSSL, glibc internals) do legitimate-but-unusual memory operations that ASAN flags as errors. Use suppression files:
# asan.supp:
interceptor_via_fun:SSL_read
interceptor_via_lib:libcrypto.so.3
Valgrind reports in multi-threaded programs: Valgrind serializes all accesses through its instrumentation, which may hide or create race conditions. Use Helgrind for race detection, but expect false positives for lock-free algorithms.
"Out of memory" when running under ASAN: ASAN needs 8x more virtual address space (for shadow memory). On 32-bit systems or systems with small vm.max_map_count, this may fail. On 64-bit: the shadow memory is mapped lazily, so physical memory usage is only 2x.
KASAN disabled for a module: Some modules opt out of KASAN for performance reasons. Check CONFIG_KASAN_MODULE_DISABLE. Performance-critical kernel subsystems (RCU, memory allocator itself) are excluded from KASAN instrumentation to prevent recursion.
Security Implications
- Memory errors (buffer overflow, use-after-free) are the most common source of security vulnerabilities. ASAN/Valgrind in CI catches these before they reach production.
- ASAN in production is NOT recommended: the increased memory footprint and slight overhead reduce availability; more importantly, ASAN includes metadata that could be exploited for information disclosure about allocation addresses.
- KFENCE in production IS recommended: it's designed for production use, catches real bugs, and has <1% overhead.
- Buffer overflows can be exploited to overwrite return addresses, function pointers, or vtable pointers. Stack canaries (
-fstack-protector-all) and ASLR provide complementary mitigations, but they don't eliminate the bugs — ASAN does (in test environments).
Performance Implications
- Valgrind Memcheck: 20-30x slowdown, 10-20x memory increase. CI only; tests should complete within reasonable timeout.
- ASAN: 1.5-2x CPU, 2-3x memory. Suitable for fast CI runs (integration tests, not load tests).
- LSan standalone (no ASAN): 1.1-1.3x overhead. Can be run in longer CI jobs.
- MSan (MemorySanitizer — uninitialized reads): 2-3x overhead. Requires all libraries to be instrumented (harder to set up than ASAN).
- KASAN Generic: 2x CPU, 2x memory. Development kernels only.
- KFENCE: <1% overhead. Production safe. Probabilistic: not every bug is caught on first occurrence.
Failure Modes and Real Incidents
Chrome browser: 1500+ bugs found by ASAN (Google, 2012-2018): After enabling ASAN in Chrome's fuzzing infrastructure and CI, Google engineers reported finding thousands of security-critical bugs in V8, Blink, and other components. Many were use-after-free and heap buffer overflows that would have been exploitable without ASAN detection.
Linux kernel KFENCE catching production crash (2022, Google): KFENCE on production Android kernels (deployed on Pixel devices) caught a use-after-free in the network driver subsystem that was causing intermittent crashes. The KFENCE report gave exact allocation and free stacks, enabling the fix in a single day. Without KFENCE, the crash vmcore showed only corrupted memory with no useful stack.
Rust vs C memory safety: Rust's ownership system eliminates use-after-free, double-free, and data races at compile time without runtime overhead. This makes ASAN unnecessary for pure Rust code. In practice, many systems mix Rust (for new code) with C/C++ (legacy) via FFI; ASAN is still needed for the C/C++ portions.
Modern Usage
- ASAN in continuous fuzzing: Google's OSS-Fuzz continuously fuzzes open-source projects with ASAN + libFuzzer. Any memory error triggers an automated bug report.
- Hardware-accelerated ASAN (HWASAN): ARM's Memory Tagging Extension (MTE, ARMv8.5-A) implements ASAN-like detection in hardware with near-zero overhead. HWASAN uses the high bits of pointer addresses as allocation tags, compared against allocation metadata on every access.
- sanitizers in Rust: Rust supports
sanitize = "address"in.cargo/config.tomlfor ASAN onunsafecode and C FFI.
Future Directions
- Capability Hardware for Security (CHERI): Cambridge/Arm research project. Hardware capabilities in pointers enforce bounds and use-after-free detection natively at the hardware level, without shadow memory or compilation overhead. CHERI-based chips (Morello prototype) demonstrate this is practical.
- Memory-safe C subset: Google, Microsoft, and DARPA are funding work on memory-safe subsets of C (SAST tools, verification) to eliminate entire classes of vulnerabilities without full language changes.
Exercises
-
ASAN bug finding: Write a C program with three deliberate bugs: (a) heap buffer overflow (write one byte past the end of a
malloc'd buffer), (b) use-after-free (access a pointer afterfree()), (c) memory leak (allocate in a loop without freeing). Compile with ASAN and verify all three are detected with useful stack traces. -
Valgrind vs ASAN comparison: Take the same buggy C program from Exercise 1. Run it under Valgrind and ASAN. Compare: (a) which errors each tool finds, (b) the quality of the error messages, (c) the runtime overhead (measure with
time). Which would you use in CI? Which for debugging a specific bug? -
KFENCE investigation: On a Linux 5.12+ system (VM is fine), compile a minimal kernel module with a deliberate use-after-free: allocate with
kmalloc,kfree, then write to the freed pointer. Load the module and call the function repeatedly until KFENCE catches it. How many calls did it take before KFENCE triggered? (Probabilistic detection.) -
Memory leak analysis with smaps: Run a server process (nginx, or write your own) for 5 minutes with memory leak injected (malloc without free in each request handler). Monitor
/proc/PID/smaps_rollupevery 30 seconds. Plot the heap RSS growth. Then run under Valgrind--leak-check=fullwith 100 test requests and identify the exact leak location. -
heaptrack memory profile: Run a Java or Go service under load with heaptrack (or use the language's native heap profiler:
HEAPPROFILE=/tmp/heap go runfor Go,-agentlib:hprof=heap=sitesfor Java). Identify the top-3 allocation call sites by total bytes allocated. Write the output as a flame-style report with bytes on the x-axis and call stack on the y-axis.
References
- Serebryany, Konstantin et al. "AddressSanitizer: A Fast Address Sanity Checker." USENIX ATC 2012.
- Elver, Marco and Potapenko, Alexander. "KFENCE: A Low-Overhead Sampling-Based Memory Safety Error Detector." Linux Kernel Documentation.
- Valgrind Documentation: https://valgrind.org/docs/manual/mc-manual.html
- AddressSanitizer wiki: https://github.com/google/sanitizers/wiki/AddressSanitizer
- Linux Kernel Documentation:
Documentation/dev-tools/kasan.rst,Documentation/dev-tools/kfence.rst - Bruening, Derek and Zhao, Qin. "Practical Memory Checking with Dr. Memory." CGO 2011.
- Gregg, Brendan. Systems Performance. 2nd ed. Chapter 7 (Memory).
- Drepper, Ulrich. "What Every Programmer Should Know About Memory." 2007. https://www.akkadia.org/drepper/cpumemory.pdf