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.
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.
Build with ASan
./tools/build.py --mode release --arch x64 --sanitizer asan \
runtime runtime_precompiled create_sdk
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.
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"
Build with MSan
./tools/build.py --mode release --arch x64 --sanitizer msan \
runtime runtime_precompiled create_sdk
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.
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"
Build with LSan
./tools/build.py --mode release --arch x64 --sanitizer lsan \
runtime runtime_precompiled create_sdk
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.
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"
Build with TSan
./tools/build.py --mode release --arch x64 --sanitizer tsan \
dart runtime runtime_precompiled create_sdk
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.
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"
Build with UBSan
./tools/build.py --mode release --arch x64 --sanitizer ubsan \
runtime runtime_precompiled create_sdk
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
Build for Android
./tools/build.py -mrelease -aarm --os=android runtime_precompiled
Add ADB to PATH
export PATH=$PATH:$PWD/third_party/android_tools/sdk/platform-tools
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.