Skip to main content
When developing the Dart SDK, various debugging tools and sanitizers can help identify memory errors, race conditions, and undefined behavior.

Memory Sanitizers

Sanitizers instrument code to detect runtime issues. They require special builds and environment configuration.

AddressSanitizer (ASan)

Detects memory errors like use-after-free, buffer overflows, and memory leaks.
1

Set environment variables

export ASAN_OPTIONS="handle_segv=0:detect_leaks=1:detect_stack_use_after_return=0:disable_coredump=0:abort_on_error=1"
export ASAN_SYMBOLIZER_PATH="$PWD/buildtools/linux-x64/clang/bin/llvm-symbolizer"
The handle_segv=0 option is crucial when running test suites, as some tests intentionally segfault.
2

Build with ASan

./tools/build.py --mode release --arch x64 --sanitizer asan \
  runtime runtime_precompiled create_sdk
3

Run tests

./tools/sdks/dart-sdk/bin/dart ./tools/test.dart \
  -n dartk-asan-linux-release-x64 \
  -N dartk-asan-linux-release-x64
Legacy approach:
./tools/gn.py -m release --asan
./tools/build.py -m release runtime
./tools/test.py -m release --builder-tag=asan -t240

MemorySanitizer (MSan)

Detects reads of uninitialized memory.
1

Set environment variables

export MSAN_OPTIONS="handle_segv=0:detect_leaks=1:detect_stack_use_after_return=0:disable_coredump=0:abort_on_error=1"
export MSAN_SYMBOLIZER_PATH="$PWD/buildtools/linux-x64/clang/bin/llvm-symbolizer"
2

Build with MSan

./tools/build.py --mode release --arch x64 --sanitizer msan \
  runtime runtime_precompiled create_sdk
3

Run tests

./tools/sdks/dart-sdk/bin/dart ./tools/test.dart \
  -n dartk-asan-linux-release-x64 \
  -N dartk-msan-linux-release-x64

LeakSanitizer (LSan)

Detects memory leaks.
1

Set environment variables

export ASAN_OPTIONS="handle_segv=0:detect_leaks=1:detect_stack_use_after_return=0:disable_coredump=0:abort_on_error=1"
export ASAN_SYMBOLIZER_PATH="$PWD/buildtools/linux-x64/clang/bin/llvm-symbolizer"
2

Build with LSan

./tools/build.py --mode release --arch x64 --sanitizer lsan \
  runtime runtime_precompiled create_sdk
3

Run tests

./tools/sdks/dart-sdk/bin/dart ./tools/test.dart \
  -n dartk-asan-linux-release-x64 \
  -N dartk-lsan-linux-release-x64

ThreadSanitizer (TSan)

Detects data races and threading issues.
1

Set environment variables

export TSAN_OPTIONS="handle_segv=0:disable_coredump=0:abort_on_error=1"
export TSAN_SYMBOLIZER_PATH="$PWD/buildtools/linux-x64/clang/bin/llvm-symbolizer"
2

Build with TSan

./tools/build.py --mode release --arch x64 --sanitizer tsan \
  dart runtime runtime_precompiled create_sdk
3

Run tests

./tools/sdks/dart-sdk/bin/dart ./tools/test.dart \
  -n dartk-asan-linux-release-x64 \
  -N dartk-tsan-linux-release-x64
Legacy approach:
./tools/gn.py -m release --tsan
./tools/build.py -m release runtime
./tools/test.py -m release

UndefinedBehaviorSanitizer (UBSan)

Detects undefined behavior like integer overflow, null pointer dereference, etc.
1

Set environment variables

export UBSAN_OPTIONS="handle_segv=0:disable_coredump=0:abort_on_error=1"
export UBSAN_SYMBOLIZER_PATH="$PWD/buildtools/linux-x64/clang/bin/llvm-symbolizer"
2

Build with UBSan

./tools/build.py --mode release --arch x64 --sanitizer ubsan \
  runtime runtime_precompiled create_sdk
3

Run tests

./tools/sdks/dart-sdk/bin/dart ./tools/test.dart \
  -n dartk-linux-release-x64 \
  -N dartk-ubsan-linux-release-x64

Debugging VM Code

Noopt Mode

Disables JIT optimization for easier debugging:
# Build noopt runtime
./tools/build.py -mdebug,release runtime_and_noopt

# Run tests without optimization
./tools/test.py -mdebug,release --noopt

ASan with VM Development

AddressSanitizer works at the C++ level and doesn’t automatically know about JIT-generated code or low-level stack manipulation.

Manual Stack Unpoisoning

Use the ASAN_UNPOISON(ptr, len) macro to inform ASan about stack regions manipulated outside normal C++ code:
// After manually manipulating stack
ASAN_UNPOISON(stack_ptr, stack_size);

Getting Real Stack Pointer

When running with detect_stack_use_after_return=1, ASan returns fake stack pointers. Use Isolate::GetCurrentStackPointer() to get the real stack pointer:
uword stack_ptr = Isolate::GetCurrentStackPointer();
This calls a pregenerated stub to bypass ASan’s instrumentation.

Testing Precompilation

Standard Precompilation

./tools/build.py -mrelease runtime_precompiled
./tools/test.py -mrelease -cprecompiler -rdart_precompiled

Precompilation on Android

1

Build for Android

./tools/build.py -mrelease -aarm --os=android runtime_precompiled
2

Add ADB to PATH

export PATH=$PATH:$PWD/third_party/android_tools/sdk/platform-tools
3

Run tests on device

./tools/test.py -mrelease -aarm --system=android \
  -cprecompiler -rdart_precompiled --use-blobs

Quick Minimal Tests

For rapid iteration during development, use these minimal test commands:

macOS

./tools/build.py -mrelease dart2js
./sdk/bin/dart2js_developer -v --categories=all \
  --package-root=out/ReleaseIA32/packages/ \
  tests/utils/dummy_compiler_test.dart

Linux

./tools/build.py -mrelease dart2js
./sdk/bin/dart2js_developer -v --categories=all \
  --package-root=out/ReleaseIA32/packages/ \
  tests/utils/dummy_compiler_test.dart

Windows

python ./tools/build.py -mrelease dart2js
sdk\bin\dart2js_developer.bat -v --categories=all \
  --package-root=out/ReleaseIA32/packages/ \
  tests/utils/dummy_compiler_test.dart
Minimal tests are quick but may miss issues. Always run full test suites before submitting.

Build docs developers (and LLMs) love