Detecting C++ Memory Errors with AddressSanitizer

AddressSanitizer (ASan) is a fast runtime memory error detector for C/C++ that uses compiler instrumentation and shadow memory to catch heap, stack, and global out‑of‑bounds accesses, use‑after‑free, double‑free and leaks, with detailed reports and configurable options for debugging and CI.

Big Data Technology Tribe
Big Data Technology Tribe
Big Data Technology Tribe
Detecting C++ Memory Errors with AddressSanitizer

1. What issues can ASan detect?

ASan can find typical memory bugs such as:

Use after free:

// heap-use-after-free
int* p = new int[10];
delete[] p;
return p[0]; // use after free

Heap buffer overflow:

// heap-buffer-overflow
int* p = new int[10];
p[10] = 1; // out‑of‑bounds write

Stack buffer overflow:

// stack-buffer-overflow
int a[10];
a[10] = 1; // out‑of‑bounds write

Double free:

// double-free
int* p = new int;
delete p;
delete p;

ASan is a runtime detector, so it only reports errors on execution paths that are actually taken.

2. Basic principle

During compilation, the compiler inserts a check before each memory access. For example, the original code x = *p; is transformed into roughly:

if (address_is_poisoned(p)) {
    report_error();
}
x = *p;

The function address_is_poisoned consults a separate "shadow memory" that records the accessibility of each byte.

Shadow Memory

ASan maintains a shadow copy of the program's memory, marking bytes as accessible or poisoned. For a heap allocation of 16 bytes, the runtime may layout memory as: [redzone][16 bytes usable][redzone] Redzones are deliberately placed before and after objects. An out‑of‑bounds write such as p[16] = 'x'; hits the right‑hand redzone, the shadow memory marks the address as poisoned, and ASan reports a heap-buffer-overflow .

Use‑after‑free detection

When memory is freed, ASan marks it as poisoned and may place it in a quarantine queue. Subsequent accesses like <code>free(p); *p = 1;</code> are caught because the shadow memory still indicates the region is invalid.

Stack and global variables

For stack variables, ASan inserts redzones between locals; for global variables, it adds redzones around each global object. Thus it can detect out‑of‑bounds accesses in heap, stack, and global memory.

3. Basic usage

Clang / GCC compilation

clang++ -g -O1 -fsanitize=address -fno-omit-frame-pointer main.cpp -o main
./main
g++ -g -O1 -fsanitize=address -fno-omit-frame-pointer main.cpp -o main
./main

The recommended flags are -fsanitize=address for both compile and link steps, together with -g and -fno-omit-frame-pointer for better stack traces. The Clang documentation suggests using at least -O1 for reasonable performance; GCC also recommends -g and mentions that ASAN_OPTIONS can control runtime behavior. Typical debug/CI flags

CXXFLAGS="-g -O1 -fsanitize=address -fno-omit-frame-pointer"
LDFLAGS="-fsanitize=address"

Both compilation and linking must include -fsanitize=address , otherwise the ASan runtime will not be linked. CMake usage

cmake -DCMAKE_BUILD_TYPE=Debug \
      -DCMAKE_CXX_FLAGS="-fsanitize=address -fno-omit-frame-pointer" \
      -DCMAKE_EXE_LINKER_FLAGS="-fsanitize=address" ..
make

Or set options per target:

target_compile_options(my_app PRIVATE
    -fsanitize=address
    -fno-omit-frame-pointer
    -g)

target_link_options(my_app PRIVATE
    -fsanitize=address)

Runtime options ASan behavior can be tuned with the ASAN_OPTIONS environment variable, e.g.:

ASAN_OPTIONS=detect_leaks=1 ./main
ASAN_OPTIONS=abort_on_error=1 ./main
ASAN_OPTIONS=halt_on_error=0 ./main
ASAN_OPTIONS=symbolize=1 ./main

If reports lack function names or source line numbers, ensure the binary was compiled with -g and that llvm-symbolizer is reachable (the ASAN_SYMBOLIZER_PATH variable can point to it).

4. How to read ASan reports

An example report:

ERROR: AddressSanitizer: heap-use-after-free
READ of size 4 at 0x...
    #0 main example.cc:10

freed by thread T0 here:
    #0 operator delete[]
    #1 main example.cc:9

previously allocated by thread T0 here:
    #0 operator new[]
    #1 main example.cc:8

Key parts to examine:

The error type line (e.g., heap-use-after-free) tells what kind of bug was found.

The READ of size 4 line indicates whether the operation was a read or write and how many bytes were accessed.

The stack traces show where the memory was allocated, freed, and incorrectly accessed.

ASan reports are richer than a plain crash because they provide the full lifecycle of the offending memory.

5. A complete example

#include <iostream>

int main(int argc, char** argv){
    int* arr = new int[4];
    delete[] arr;
    std::cout << arr[0] << std::endl; // use‑after‑free
    return 0;
}

Compile and run:

clang++ -g -O1 -fsanitize=address -fno-omit-frame-pointer uaf.cpp -o uaf
./uaf

The execution prints an error similar to the one shown above, and the source line numbers in the report guide the fix.

6. Common considerations

ASan is intended for testing environments; it should not be linked into production binaries because its runtime is not designed for production‑level safety and adds noticeable overhead (Clang documentation cites a typical ~2× slowdown). The usual practice is to enable ASan for development, unit tests, CI, and fuzzing, and disable it for release builds. ASan only detects errors on executed paths, so untested code remains unchecked. It also does not replace other sanitizers: ThreadSanitizer (TSan) for data races, UndefinedBehaviorSanitizer (UBSan) for undefined behavior, and MemorySanitizer (MSan) for uninitialized memory reads.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

C++memory debuggingshadow memoryAddressSanitizerruntime sanitizers
Big Data Technology Tribe
Written by

Big Data Technology Tribe

Focused on computer science and cutting‑edge tech, we distill complex knowledge into clear, actionable insights. We track tech evolution, share industry trends and deep analysis, helping you keep learning, boost your technical edge, and ride the digital wave forward.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.