Sanitizers
Sanitizers 是较轻量级的内存检测工具, 最初是在 C/C++ 编译器中实现的.
Rustc 支持的 sanitizer 种类有:
- AddressSanitizer, 选项名是
address
, 支持检测以下问题:- 堆内存越界 (out-of-bounds of heap), 栈内存越界, 全局变量越界
- 访问已被释放的内存 use after free
- 重复释放的内存 double free
- 释放无效内存 invalid free
- 内存没有被释放, 造成泄露 memory leak
- LeakSanitizer, 选项名是
leak
, 用于检测内存泄露, 可以配合address
选项使用 - MemorySanitizer, 选项名是
memory
, 用于检测读取未初始化的内存 - ThreadSanitizer, 选项名是
thread
, 用于检测数据竞态 (data race) - ControlFlowIntegrity
- Hardware-associated AddressSanitizer
- KernelControlFlowIntegrity
目前只有 nightly 通道的 rust 工具链支持 Sanitizers, 使用 -Z santizier=xxx
来激活相应的工具.
检测内存泄露
比如, 下面的示例代码中有两个泄露位点:
use std::mem; fn main() { let msg = String::from("Hello, Rust"); assert_eq!(msg.chars().count(), 11); // 创建 ManuallyDrop, 阻止 String::drop() 方法被调用. mem::forget(msg); let numbers = vec![1, 2, 3, 5, 8, 13]; let slice = numbers.into_boxed_slice(); // 转换成原始指针, 不会再调用 Vec<i32>::drop() 方法 let _ptr: *mut [i32] = Box::leak(slice); }
使用以下命令, 运行 sanitizer:
RUSTFLAGS="-Zsanitizer=address" cargo +nightly run --bin san-memory-leak
运行后产生了如下的日志:
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.10s
Running `/tmp/intro-to-rust/target/debug/san-memory-leak`
=================================================================
==26078==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 24 byte(s) in 1 object(s) allocated from:
#0 0x55da5c1e5e5f in malloc /rustc/llvm/src/llvm-project/compiler-rt/lib/asan/asan_malloc_linux.cpp:68:3
#1 0x55da5c21076f in alloc::alloc::alloc::h18d98aef82814903 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/alloc/src/alloc.rs:100:9
#2 0x55da5c210a4e in alloc::alloc::Global::alloc_impl::hdf5500cbdd5c13e5 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/alloc/src/alloc.rs:183:73
#3 0x55da5c2105aa in _$LT$alloc..alloc..Global$u20$as$u20$core..alloc..Allocator$GT$::allocate::h57656c0cb9113886 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/alloc/src/alloc.rs:243:9
#4 0x55da5c2105aa in alloc::alloc::exchange_malloc::h4869f251cc126da0 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/alloc/src/alloc.rs:332:18
#5 0x55da5c213a9a in core::ops::function::FnOnce::call_once::h179e0f184daf3550 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/core/src/ops/function.rs:250:5
#6 0x55da5c22ef0c in core::ops::function::impls::_$LT$impl$u20$core..ops..function..FnOnce$LT$A$GT$$u20$for$u20$$RF$F$GT$::call_once::h8ee6b536c2e4e076 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/core/src/ops/function.rs:284:13
#7 0x55da5c22ef0c in std::panicking::try::do_call::h5c8c98de8ed5bd5b /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/panicking.rs:553:40
#8 0x55da5c22ef0c in std::panicking::try::h6315052de0e5fa0e /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/panicking.rs:517:19
#9 0x55da5c22ef0c in std::panic::catch_unwind::h1530d3793f92a4bb /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/panic.rs:350:14
#10 0x55da5c22ef0c in std::rt::lang_start_internal::_$u7b$$u7b$closure$u7d$$u7d$::he545ff4063dfc2c8 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/rt.rs:141:48
#11 0x55da5c22ef0c in std::panicking::try::do_call::h09c77e8b42da26d9 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/panicking.rs:553:40
#12 0x55da5c22ef0c in std::panicking::try::h7a9b2c58b7302b3b /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/panicking.rs:517:19
#13 0x55da5c22ef0c in std::panic::catch_unwind::h464a2cd7183a7af5 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/panic.rs:350:14
#14 0x55da5c22ef0c in std::rt::lang_start_internal::h99fdbebdafe8d634 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/rt.rs:141:20
#15 0x55da5c214db8 in std::rt::lang_start::hc7e4f2c854274dbd /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/rt.rs:158:17
#16 0x55da5c21054d in main (/tmp/intro-to-rust/target/debug/san-memory-leak+0xbb54d) (BuildId: 161357dd922a2020d2b2bd4d81313ce5fb2b7a72)
Direct leak of 11 byte(s) in 1 object(s) allocated from:
#0 0x55da5c1e5e5f in malloc /rustc/llvm/src/llvm-project/compiler-rt/lib/asan/asan_malloc_linux.cpp:68:3
#1 0x55da5c21076f in alloc::alloc::alloc::h18d98aef82814903 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/alloc/src/alloc.rs:100:9
#2 0x55da5c210a4e in alloc::alloc::Global::alloc_impl::hdf5500cbdd5c13e5 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/alloc/src/alloc.rs:183:73
#3 0x55da5c211638 in _$LT$alloc..alloc..Global$u20$as$u20$core..alloc..Allocator$GT$::allocate::h57656c0cb9113886 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/alloc/src/alloc.rs:243:9
#4 0x55da5c21304c in alloc::raw_vec::RawVec$LT$T$C$A$GT$::with_capacity_in::hb834086c0ea4b1b2 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/alloc/src/raw_vec.rs:158:15
#5 0x55da5c21304c in alloc::vec::Vec$LT$T$C$A$GT$::with_capacity_in::hd1af89fce9cfcc1f /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/alloc/src/vec/mod.rs:699:20
#6 0x55da5c21304c in _$LT$T$u20$as$u20$alloc..slice..hack..ConvertVec$GT$::to_vec::hef44f66f7fe89ef0 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/alloc/src/slice.rs:162:25
#7 0x55da5c2149e4 in alloc::slice::hack::to_vec::hbb17b02e50387cfa /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/alloc/src/slice.rs:111:9
#8 0x55da5c2149e4 in alloc::slice::_$LT$impl$u20$$u5b$T$u5d$$GT$::to_vec_in::ha6ad9e9219b6abe7 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/alloc/src/slice.rs:462:9
#9 0x55da5c2149e4 in alloc::slice::_$LT$impl$u20$$u5b$T$u5d$$GT$::to_vec::h37bb05672b9af49e /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/alloc/src/slice.rs:437:14
#10 0x55da5c2149e4 in alloc::slice::_$LT$impl$u20$alloc..borrow..ToOwned$u20$for$u20$$u5b$T$u5d$$GT$::to_owned::h26d174d6cec3659e /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/alloc/src/slice.rs:844:14
#11 0x55da5c2149e4 in alloc::str::_$LT$impl$u20$alloc..borrow..ToOwned$u20$for$u20$str$GT$::to_owned::h739fe38078478dff /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/alloc/src/str.rs:212:62
#12 0x55da5c2149e4 in _$LT$alloc..string..String$u20$as$u20$core..convert..From$LT$$RF$str$GT$$GT$::from::hab63273f3f6b8c9b /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/alloc/src/string.rs:2715:11
#13 0x55da5c20ffff in san_memory_leak::main::hcfa228fc530e0524 /tmp/intro-to-rust/code/memory/src/bin/san-memory-leak.rs:8:15
#14 0x55da5c213a9a in core::ops::function::FnOnce::call_once::h179e0f184daf3550 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/core/src/ops/function.rs:250:5
#15 0x55da5c22ef0c in core::ops::function::impls::_$LT$impl$u20$core..ops..function..FnOnce$LT$A$GT$$u20$for$u20$$RF$F$GT$::call_once::h8ee6b536c2e4e076 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/core/src/ops/function.rs:284:13
#16 0x55da5c22ef0c in std::panicking::try::do_call::h5c8c98de8ed5bd5b /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/panicking.rs:553:40
#17 0x55da5c22ef0c in std::panicking::try::h6315052de0e5fa0e /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/panicking.rs:517:19
#18 0x55da5c22ef0c in std::panic::catch_unwind::h1530d3793f92a4bb /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/panic.rs:350:14
#19 0x55da5c22ef0c in std::rt::lang_start_internal::_$u7b$$u7b$closure$u7d$$u7d$::he545ff4063dfc2c8 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/rt.rs:141:48
#20 0x55da5c22ef0c in std::panicking::try::do_call::h09c77e8b42da26d9 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/panicking.rs:553:40
#21 0x55da5c22ef0c in std::panicking::try::h7a9b2c58b7302b3b /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/panicking.rs:517:19
#22 0x55da5c22ef0c in std::panic::catch_unwind::h464a2cd7183a7af5 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/panic.rs:350:14
#23 0x55da5c22ef0c in std::rt::lang_start_internal::h99fdbebdafe8d634 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/rt.rs:141:20
#24 0x55da5c214db8 in std::rt::lang_start::hc7e4f2c854274dbd /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/rt.rs:158:17
#25 0x55da5c21054d in main (/tmp/intro-to-rust/target/debug/san-memory-leak+0xbb54d) (BuildId: 161357dd922a2020d2b2bd4d81313ce5fb2b7a72)
SUMMARY: AddressSanitizer: 35 byte(s) leaked in 2 allocation(s).
尽管它成功检测出了两处内存泄露, 但是只有其中一个错误包含了精确的内存泄露位置:
#13 0x55da5c20ffff in san_memory_leak::main::hcfa228fc530e0524 /tmp/san-memory-leak.rs:8:15
检测内存越界 Out of bounds
下面的代码示例中有三处内存越界发生:
use std::ptr; fn main() { // numbers 在堆内存上分配的空间只有 3 个字节. let mut numbers: Vec<u8> = vec![0, 1, 2]; // 越界写入 unsafe { let numbers_ptr = numbers.as_mut_ptr(); // 向 numbers 的堆内存连续写入 4 个字节, 最后一个字节是越界的. ptr::write_bytes(numbers_ptr, 0xf1, 4); } // 越界读取 let _off_last_byte: u8 = unsafe { // 从 numbers 的堆内存读取第 4 个字节 *numbers.as_ptr().offset(4) }; let mut numbers2: [i32; 3] = [0, 1, 2]; unsafe { let numbers2_ptr = ptr::addr_of_mut!(numbers2); // 栈内存越界写入 ptr::write_bytes(numbers2_ptr, 0x1f, 2); } assert_eq!(numbers2[0], 0x1f1f1f1f); }
上面代码中对 numbers
的堆内存读写都是越界的:
对变量 numbers2
的栈内存写入也是越界的, 它只有 12 个字节的空间, 却写入了 24 个字节的数据:
使用以下命令, 运行 sanitizer:
RUSTFLAGS="-Zsanitizer=address,leak" cargo +nightly run --bin san-out-of-bounds
只有针对写堆内存越界的错误给出了精准的定位:
#2 0x55998e7730c7 in san_out_of_bounds::main::h3f63e38c2d1ef70e /tmp/san-out-of-bounds.rs:15:9
访问已被释放的内存 use after free
以下的代码示例中, 错误地访问了已经被释放的堆内存:
use std::ptr; fn main() { let mut msg = String::from("Hello, Rust"); let msg_ptr = msg.as_mut_ptr(); // 释放 msg 的堆内存 drop(msg); unsafe { // 将 msg 中的字符 `R` 转为小写 ptr::write_bytes(msg_ptr.offset(8), b'r', 1); } }
使用 address sanitizer 来检测它:
RUSTFLAGS="-Zsanitizer=address,leak" cargo +nightly run --bin san-use-after-free
得到如下的报告:
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.11s
Running `/tmp/san-use-after-free`
=================================================================
==48883==ERROR: AddressSanitizer: heap-use-after-free on address 0x502000000018 at pc 0x55c491cfd1f5 bp 0x7ffc8dc94270 sp 0x7ffc8dc93a40
WRITE of size 1 at 0x502000000018 thread T0
#0 0x55c491cfd1f4 in __asan_memset /rustc/llvm/src/llvm-project/compiler-rt/lib/asan/asan_interceptors_memintrinsics.cpp:67:3
#1 0x55c491d2a4be in core::intrinsics::write_bytes::h275db0bf8dfd8b81 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/core/src/intrinsics.rs:3132:9
#2 0x55c491d2a4be in san_use_after_free::main::ha6e8e0b3b7b7c0d4 /tmp/san-use-after-free.rs:14:9
#3 0x55c491d293ca in core::ops::function::FnOnce::call_once::h9a7e669c52058242 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/core/src/ops/function.rs:250:5
#4 0x55c491d2a73d in std::sys::backtrace::__rust_begin_short_backtrace::h24fb90d0dbf25fd4 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/sys/backtrace.rs:155:18
#5 0x55c491d29fb4 in std::rt::lang_start::_$u7b$$u7b$closure$u7d$$u7d$::hcbc0207cb2102ed2 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/rt.rs:159:18
#6 0x55c491d4589c in core::ops::function::impls::_$LT$impl$u20$core..ops..function..FnOnce$LT$A$GT$$u20$for$u20$$RF$F$GT$::call_once::h8ee6b536c2e4e076 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/core/src/ops/function.rs:284:13
#7 0x55c491d4589c in std::panicking::try::do_call::h5c8c98de8ed5bd5b /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/panicking.rs:553:40
#8 0x55c491d4589c in std::panicking::try::h6315052de0e5fa0e /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/panicking.rs:517:19
#9 0x55c491d4589c in std::panic::catch_unwind::h1530d3793f92a4bb /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/panic.rs:350:14
#10 0x55c491d4589c in std::rt::lang_start_internal::_$u7b$$u7b$closure$u7d$$u7d$::he545ff4063dfc2c8 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/rt.rs:141:48
#11 0x55c491d4589c in std::panicking::try::do_call::h09c77e8b42da26d9 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/panicking.rs:553:40
#12 0x55c491d4589c in std::panicking::try::h7a9b2c58b7302b3b /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/panicking.rs:517:19
#13 0x55c491d4589c in std::panic::catch_unwind::h464a2cd7183a7af5 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/panic.rs:350:14
#14 0x55c491d4589c in std::rt::lang_start_internal::h99fdbebdafe8d634 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/rt.rs:141:20
#15 0x55c491d29e58 in std::rt::lang_start::had829c785f68a77b /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/rt.rs:158:17
#16 0x55c491d2a61d in main (/tmp/san-use-after-free+0xbc61d) (BuildId: 40b07716a65da8f8519e83d784d142834d3684f2)
#17 0x7efe01d08c89 in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
#18 0x7efe01d08d44 in __libc_start_main csu/../csu/libc-start.c:360:3
#19 0x55c491c7bc90 in _start (/tmp/san-use-after-free+0xdc90) (BuildId: 40b07716a65da8f8519e83d784d142834d3684f2)
0x502000000018 is located 8 bytes inside of 11-byte region [0x502000000010,0x50200000001b)
freed by thread T0 here:
#0 0x55c491cfea46 in free /rustc/llvm/src/llvm-project/compiler-rt/lib/asan/asan_malloc_linux.cpp:52:3
#1 0x55c491d2ba06 in alloc::alloc::dealloc::he34fc8c895854eae /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/alloc/src/alloc.rs:119:14
#2 0x55c491d2ba06 in _$LT$alloc..alloc..Global$u20$as$u20$core..alloc..Allocator$GT$::deallocate::hd36615ec06478e33 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/alloc/src/alloc.rs:256:22
#3 0x55c491d2977a in _$LT$alloc..raw_vec..RawVec$LT$T$C$A$GT$$u20$as$u20$core..ops..drop..Drop$GT$::drop::h4f8728bad42a964e /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/alloc/src/raw_vec.rs:600:22
#4 0x55c491d295c9 in core::ptr::drop_in_place$LT$alloc..raw_vec..RawVec$LT$u8$GT$$GT$::hf72af14d538b6207 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/core/src/ptr/mod.rs:542:1
#5 0x55c491d293ca in core::ops::function::FnOnce::call_once::h9a7e669c52058242 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/core/src/ops/function.rs:250:5
#6 0x55c491d4589c in core::ops::function::impls::_$LT$impl$u20$core..ops..function..FnOnce$LT$A$GT$$u20$for$u20$$RF$F$GT$::call_once::h8ee6b536c2e4e076 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/core/src/ops/function.rs:284:13
#7 0x55c491d4589c in std::panicking::try::do_call::h5c8c98de8ed5bd5b /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/panicking.rs:553:40
#8 0x55c491d4589c in std::panicking::try::h6315052de0e5fa0e /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/panicking.rs:517:19
#9 0x55c491d4589c in std::panic::catch_unwind::h1530d3793f92a4bb /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/panic.rs:350:14
#10 0x55c491d4589c in std::rt::lang_start_internal::_$u7b$$u7b$closure$u7d$$u7d$::he545ff4063dfc2c8 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/rt.rs:141:48
#11 0x55c491d4589c in std::panicking::try::do_call::h09c77e8b42da26d9 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/panicking.rs:553:40
#12 0x55c491d4589c in std::panicking::try::h7a9b2c58b7302b3b /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/panicking.rs:517:19
#13 0x55c491d4589c in std::panic::catch_unwind::h464a2cd7183a7af5 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/panic.rs:350:14
#14 0x55c491d4589c in std::rt::lang_start_internal::h99fdbebdafe8d634 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/rt.rs:141:20
#15 0x55c491d29e58 in std::rt::lang_start::had829c785f68a77b /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/rt.rs:158:17
#16 0x55c491d2a61d in main (/tmp/san-use-after-free+0xbc61d) (BuildId: 40b07716a65da8f8519e83d784d142834d3684f2)
previously allocated by thread T0 here:
#0 0x55c491cfecdf in malloc /rustc/llvm/src/llvm-project/compiler-rt/lib/asan/asan_malloc_linux.cpp:68:3
#1 0x55c491d2b41f in alloc::alloc::alloc::ha10955ac768529c4 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/alloc/src/alloc.rs:100:9
#2 0x55c491d2b6fe in alloc::alloc::Global::alloc_impl::h952e25fc69d013f2 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/alloc/src/alloc.rs:183:73
#3 0x55c491d2ba68 in _$LT$alloc..alloc..Global$u20$as$u20$core..alloc..Allocator$GT$::allocate::h3f5cd0999b0016dd /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/alloc/src/alloc.rs:243:9
#4 0x55c491d2992c in alloc::raw_vec::RawVec$LT$T$C$A$GT$::with_capacity_in::h90a3c53535a47f9c /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/alloc/src/raw_vec.rs:158:15
#5 0x55c491d2992c in alloc::vec::Vec$LT$T$C$A$GT$::with_capacity_in::h727aedd763542a12 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/alloc/src/vec/mod.rs:699:20
#6 0x55c491d2992c in _$LT$T$u20$as$u20$alloc..slice..hack..ConvertVec$GT$::to_vec::h55b023e79ecdd1e4 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/alloc/src/slice.rs:162:25
#7 0x55c491d29c84 in alloc::slice::hack::to_vec::h4aab7a9196b5dd80 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/alloc/src/slice.rs:111:9
#8 0x55c491d29c84 in alloc::slice::_$LT$impl$u20$$u5b$T$u5d$$GT$::to_vec_in::h59ef1c2003b2da43 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/alloc/src/slice.rs:462:9
#9 0x55c491d29c84 in alloc::slice::_$LT$impl$u20$$u5b$T$u5d$$GT$::to_vec::h765ebc2e7b673718 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/alloc/src/slice.rs:437:14
#10 0x55c491d29c84 in alloc::slice::_$LT$impl$u20$alloc..borrow..ToOwned$u20$for$u20$$u5b$T$u5d$$GT$::to_owned::h78af1272be58f355 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/alloc/src/slice.rs:844:14
#11 0x55c491d29c84 in alloc::str::_$LT$impl$u20$alloc..borrow..ToOwned$u20$for$u20$str$GT$::to_owned::h881d4cf593dc69cf /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/alloc/src/str.rs:212:62
#12 0x55c491d29c84 in _$LT$alloc..string..String$u20$as$u20$core..convert..From$LT$$RF$str$GT$$GT$::from::he993a3d7b8799ab9 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/alloc/src/string.rs:2715:11
#13 0x55c491d2a3d5 in san_use_after_free::main::ha6e8e0b3b7b7c0d4 /tmp/san-use-after-free.rs:8:19
#14 0x55c491d293ca in core::ops::function::FnOnce::call_once::h9a7e669c52058242 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/core/src/ops/function.rs:250:5
#15 0x55c491d4589c in core::ops::function::impls::_$LT$impl$u20$core..ops..function..FnOnce$LT$A$GT$$u20$for$u20$$RF$F$GT$::call_once::h8ee6b536c2e4e076 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/core/src/ops/function.rs:284:13
#16 0x55c491d4589c in std::panicking::try::do_call::h5c8c98de8ed5bd5b /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/panicking.rs:553:40
#17 0x55c491d4589c in std::panicking::try::h6315052de0e5fa0e /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/panicking.rs:517:19
#18 0x55c491d4589c in std::panic::catch_unwind::h1530d3793f92a4bb /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/panic.rs:350:14
#19 0x55c491d4589c in std::rt::lang_start_internal::_$u7b$$u7b$closure$u7d$$u7d$::he545ff4063dfc2c8 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/rt.rs:141:48
#20 0x55c491d4589c in std::panicking::try::do_call::h09c77e8b42da26d9 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/panicking.rs:553:40
#21 0x55c491d4589c in std::panicking::try::h7a9b2c58b7302b3b /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/panicking.rs:517:19
#22 0x55c491d4589c in std::panic::catch_unwind::h464a2cd7183a7af5 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/panic.rs:350:14
#23 0x55c491d4589c in std::rt::lang_start_internal::h99fdbebdafe8d634 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/rt.rs:141:20
#24 0x55c491d29e58 in std::rt::lang_start::had829c785f68a77b /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/rt.rs:158:17
#25 0x55c491d2a61d in main (/tmp/san-use-after-free+0xbc61d) (BuildId: 40b07716a65da8f8519e83d784d142834d3684f2)
SUMMARY: AddressSanitizer: heap-use-after-free /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/core/src/intrinsics.rs:3132:9 in core::intrinsics::write_bytes::h275db0bf8dfd8b81
Shadow bytes around the buggy address:
0x501ffffffd80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x501ffffffe00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x501ffffffe80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x501fffffff00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x501fffffff80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x502000000000: fa fa fd[fd]fa fa fa fa fa fa fa fa fa fa fa fa
0x502000000080: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x502000000100: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x502000000180: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x502000000200: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x502000000280: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
==48883==ABORTING
报告里面写明了错误类型 heap-use-after-free
, 并精准定位了出错的位置:
#2 0x55c491d2a4be in san_use_after_free::main::ha6e8e0b3b7b7c0d4 /tmp/san-use-after-free.rs:14:9
检测循环引用 Cyclic references
循环引用的问题常出现在 Rc/Arc 等以引用计数的方式来管理对象的地方. 以下一个示例展示了二叉树中的循环引用问题:
use std::cell::RefCell; use std::rc::Rc; #[derive(Default)] struct TreeNode { left: Option<Rc<RefCell<TreeNode>>>, right: Option<Rc<RefCell<TreeNode>>>, val: i32, } impl TreeNode { #[must_use] #[inline] pub const fn is_leaf(&self) -> bool { self.left.is_none() && self.right.is_none() } } impl Drop for TreeNode { fn drop(&mut self) { println!("Will drop node with value: {}", self.val); } } fn main() { let leaf_node = Rc::new(RefCell::new(TreeNode::default())); assert!(leaf_node.borrow().is_leaf()); let node1 = Rc::new(RefCell::new(TreeNode { left: None, right: Some(leaf_node.clone()), val: 42, })); let node2 = Rc::new(RefCell::new(TreeNode { left: Some(leaf_node.clone()), right: Some(node1.clone()), val: 12, })); // 制造一个循环引用 node1.borrow_mut().left = Some(node2.clone()); // 程序运行结束后, node1 和 node2 都不会被正确的释放 }
循环引用会导致节点上的对象不能被正常的释放, 内存不会回收并出现内存泄露的问题.
Sanitizer 可以检测到内存泄露的情况, 使用以下命令:
RUSTFLAGS="-Zsanitizer=address,leak" cargo +nightly run --bin san-cyclic-references
可以得到以下日志报告:
Compiling libc v0.2.155
Compiling memory v0.1.0 (/tmp/intro-to-rust/code/memory)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 1.46s
Running `/tmp/intro-to-rust/target/debug/san-cyclic-references`
=================================================================
==154957==ERROR: LeakSanitizer: detected memory leaks
Indirect leak of 48 byte(s) in 1 object(s) allocated from:
#0 0x55e98639e10f in malloc /rustc/llvm/src/llvm-project/compiler-rt/lib/asan/asan_malloc_linux.cpp:68:3
#1 0x55e9863c961f in alloc::alloc::alloc::h71b9c2fa3833688e /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/alloc/src/alloc.rs:100:9
#2 0x55e9863c98fe in alloc::alloc::Global::alloc_impl::h4661849ad8696522 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/alloc/src/alloc.rs:183:73
#3 0x55e9863c945a in _$LT$alloc..alloc..Global$u20$as$u20$core..alloc..Allocator$GT$::allocate::h89a094a661859bcd /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/alloc/src/alloc.rs:243:9
#4 0x55e9863c945a in alloc::alloc::exchange_malloc::ha5a75c30f8f85d71 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/alloc/src/alloc.rs:332:18
#5 0x55e9863c9fd2 in san_cyclic_references::main::h92fbd07b3584710d /tmp/intro-to-rust/code/memory/src/bin/san-cyclic-references.rs:33:17
#6 0x55e9863c822a in core::ops::function::FnOnce::call_once::h691941b5fcd7eed2 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/core/src/ops/function.rs:250:5
#7 0x55e9863e483c in core::ops::function::impls::_$LT$impl$u20$core..ops..function..FnOnce$LT$A$GT$$u20$for$u20$$RF$F$GT$::call_once::h8ee6b536c2e4e076 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/core/src/ops/function.rs:284:13
#8 0x55e9863e483c in std::panicking::try::do_call::h5c8c98de8ed5bd5b /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/panicking.rs:553:40
#9 0x55e9863e483c in std::panicking::try::h6315052de0e5fa0e /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/panicking.rs:517:19
#10 0x55e9863e483c in std::panic::catch_unwind::h1530d3793f92a4bb /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/panic.rs:350:14
#11 0x55e9863e483c in std::rt::lang_start_internal::_$u7b$$u7b$closure$u7d$$u7d$::he545ff4063dfc2c8 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/rt.rs:141:48
#12 0x55e9863e483c in std::panicking::try::do_call::h09c77e8b42da26d9 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/panicking.rs:553:40
#13 0x55e9863e483c in std::panicking::try::h7a9b2c58b7302b3b /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/panicking.rs:517:19
#14 0x55e9863e483c in std::panic::catch_unwind::h464a2cd7183a7af5 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/panic.rs:350:14
#15 0x55e9863e483c in std::rt::lang_start_internal::h99fdbebdafe8d634 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/rt.rs:141:20
#16 0x55e9863c91d8 in std::rt::lang_start::h554a4489af6c7e14 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/rt.rs:158:17
#17 0x55e9863ca29d in main (/tmp/intro-to-rust/target/debug/san-cyclic-references+0xbd29d) (BuildId: 5dc7b4586c73e6fdcab7c038bd63e8862b0b9ec5)
Indirect leak of 48 byte(s) in 1 object(s) allocated from:
#0 0x55e98639e10f in malloc /rustc/llvm/src/llvm-project/compiler-rt/lib/asan/asan_malloc_linux.cpp:68:3
#1 0x55e9863c961f in alloc::alloc::alloc::h71b9c2fa3833688e /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/alloc/src/alloc.rs:100:9
#2 0x55e9863c98fe in alloc::alloc::Global::alloc_impl::h4661849ad8696522 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/alloc/src/alloc.rs:183:73
#3 0x55e9863c945a in _$LT$alloc..alloc..Global$u20$as$u20$core..alloc..Allocator$GT$::allocate::h89a094a661859bcd /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/alloc/src/alloc.rs:243:9
#4 0x55e9863c945a in alloc::alloc::exchange_malloc::ha5a75c30f8f85d71 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/alloc/src/alloc.rs:332:18
#5 0x55e9863ca05c in san_cyclic_references::main::h92fbd07b3584710d /tmp/intro-to-rust/code/memory/src/bin/san-cyclic-references.rs:38:17
#6 0x55e9863c822a in core::ops::function::FnOnce::call_once::h691941b5fcd7eed2 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/core/src/ops/function.rs:250:5
#7 0x55e9863e483c in core::ops::function::impls::_$LT$impl$u20$core..ops..function..FnOnce$LT$A$GT$$u20$for$u20$$RF$F$GT$::call_once::h8ee6b536c2e4e076 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/core/src/ops/function.rs:284:13
#8 0x55e9863e483c in std::panicking::try::do_call::h5c8c98de8ed5bd5b /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/panicking.rs:553:40
#9 0x55e9863e483c in std::panicking::try::h6315052de0e5fa0e /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/panicking.rs:517:19
#10 0x55e9863e483c in std::panic::catch_unwind::h1530d3793f92a4bb /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/panic.rs:350:14
#11 0x55e9863e483c in std::rt::lang_start_internal::_$u7b$$u7b$closure$u7d$$u7d$::he545ff4063dfc2c8 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/rt.rs:141:48
#12 0x55e9863e483c in std::panicking::try::do_call::h09c77e8b42da26d9 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/panicking.rs:553:40
#13 0x55e9863e483c in std::panicking::try::h7a9b2c58b7302b3b /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/panicking.rs:517:19
#14 0x55e9863e483c in std::panic::catch_unwind::h464a2cd7183a7af5 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/panic.rs:350:14
#15 0x55e9863e483c in std::rt::lang_start_internal::h99fdbebdafe8d634 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/rt.rs:141:20
#16 0x55e9863c91d8 in std::rt::lang_start::h554a4489af6c7e14 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/rt.rs:158:17
#17 0x55e9863ca29d in main (/tmp/intro-to-rust/target/debug/san-cyclic-references+0xbd29d) (BuildId: 5dc7b4586c73e6fdcab7c038bd63e8862b0b9ec5)
Indirect leak of 48 byte(s) in 1 object(s) allocated from:
#0 0x55e98639e10f in malloc /rustc/llvm/src/llvm-project/compiler-rt/lib/asan/asan_malloc_linux.cpp:68:3
#1 0x55e9863c961f in alloc::alloc::alloc::h71b9c2fa3833688e /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/alloc/src/alloc.rs:100:9
#2 0x55e9863c98fe in alloc::alloc::Global::alloc_impl::h4661849ad8696522 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/alloc/src/alloc.rs:183:73
#3 0x55e9863c945a in _$LT$alloc..alloc..Global$u20$as$u20$core..alloc..Allocator$GT$::allocate::h89a094a661859bcd /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/alloc/src/alloc.rs:243:9
#4 0x55e9863c945a in alloc::alloc::exchange_malloc::ha5a75c30f8f85d71 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/alloc/src/alloc.rs:332:18
#5 0x55e9863c9e8f in san_cyclic_references::main::h92fbd07b3584710d /tmp/intro-to-rust/code/memory/src/bin/san-cyclic-references.rs:30:21
#6 0x55e9863c822a in core::ops::function::FnOnce::call_once::h691941b5fcd7eed2 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/core/src/ops/function.rs:250:5
#7 0x55e9863e483c in core::ops::function::impls::_$LT$impl$u20$core..ops..function..FnOnce$LT$A$GT$$u20$for$u20$$RF$F$GT$::call_once::h8ee6b536c2e4e076 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/core/src/ops/function.rs:284:13
#8 0x55e9863e483c in std::panicking::try::do_call::h5c8c98de8ed5bd5b /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/panicking.rs:553:40
#9 0x55e9863e483c in std::panicking::try::h6315052de0e5fa0e /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/panicking.rs:517:19
#10 0x55e9863e483c in std::panic::catch_unwind::h1530d3793f92a4bb /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/panic.rs:350:14
#11 0x55e9863e483c in std::rt::lang_start_internal::_$u7b$$u7b$closure$u7d$$u7d$::he545ff4063dfc2c8 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/rt.rs:141:48
#12 0x55e9863e483c in std::panicking::try::do_call::h09c77e8b42da26d9 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/panicking.rs:553:40
#13 0x55e9863e483c in std::panicking::try::h7a9b2c58b7302b3b /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/panicking.rs:517:19
#14 0x55e9863e483c in std::panic::catch_unwind::h464a2cd7183a7af5 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/panic.rs:350:14
#15 0x55e9863e483c in std::rt::lang_start_internal::h99fdbebdafe8d634 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/rt.rs:141:20
#16 0x55e9863c91d8 in std::rt::lang_start::h554a4489af6c7e14 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/rt.rs:158:17
#17 0x55e9863ca29d in main (/tmp/intro-to-rust/target/debug/san-cyclic-references+0xbd29d) (BuildId: 5dc7b4586c73e6fdcab7c038bd63e8862b0b9ec5)
SUMMARY: AddressSanitizer: 144 byte(s) leaked in 3 allocation(s).
报告中确实有发现内存泄露的情况, 并且给出了位置所在:
#5 0x55e9863c9fd2 in san_cyclic_references::main::h92fbd07b3584710d /tmp/intro-to-rust/code/memory/src/bin/san-cyclic-references.rs:33:17
#5 0x55e9863ca05c in san_cyclic_references::main::h92fbd07b3584710d /tmp/intro-to-rust/code/memory/src/bin/san-cyclic-references.rs:38:17
检测数据竞态 Data race
多个线程访问同一块内存时, 应该使用互斥锁等手段, 确保不会发生 data race condition.
另外, 如果使用了线程本地存储 (Thread local storage) 的话, 它在每个线程中被单独保存了一份, 各线程只会访问内部的那一份克隆, 所以不存在 data race.
看下面的例子:
use std::cell::Cell; use std::thread; // 初始化为 1. thread_local!(static TLS_COUNTER: Cell<i32> = const { Cell::new(1) }); // 全局变量, 该变量位于 data segment. static mut SHARED_COUNTER: i32 = 1; fn main() { // 设置主线程的 TLS_COUNTER 实例的值为 2. TLS_COUNTER.set(2); let t1 = thread::spawn(move || { // 线程启动时, TLS_COUNTER 的值是 1. assert_eq!(TLS_COUNTER.get(), 1); // 修改线程内部的 TLS_COUNTER 实例. TLS_COUNTER.set(3); }); TLS_COUNTER.set(4); t1.join().unwrap(); // 读取主线程中的 TLS_COUNTER 实例. assert_eq!(TLS_COUNTER.get(), 4); // 没有任何保护手段的情况下, 直接访问全局变量. unsafe { SHARED_COUNTER = 2; } let t2 = thread::spawn(|| { unsafe { // 可能发生 data race SHARED_COUNTER = 3; } }); // 可能发生 data race unsafe { SHARED_COUNTER = 4; } t2.join().unwrap(); // 无法确定 SHARED_COUNTER 的值 unsafe { assert!(SHARED_COUNTER == 3 || SHARED_COUNTER == 4); } let _x = 11; }
使用以下命令来检测它:
RUSTFLAGS="-Zsanitizer=thread" cargo +nightly run --bin san-data-race
会得到这个报告:
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.02s
Running `/tmp/intro-to-rust/target/debug/san-data-race`
==================
WARNING: ThreadSanitizer: data race (pid=174565)
Write of size 4 at 0x558040da1948 by thread T2:
#0 san_data_race::main::_$u7b$$u7b$closure$u7d$$u7d$::hca1d1aa2bd214a46 /tmp/intro-to-rust/code/memory/src/bin/san-data-race.rs:30:13 (san-data-race+0x98906) (BuildId: abaff10be3c90c7a985911bf9fb769fbad66acc6)
#1 std::sys::backtrace::__rust_begin_short_backtrace::he6b9930aee5e4b5d /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/sys/backtrace.rs:155:18 (san-data-race+0x98cd2) (BuildId: abaff10be3c90c7a985911bf9fb769fbad66acc6)
#2 std::thread::Builder::spawn_unchecked_::_$u7b$$u7b$closure$u7d$$u7d$::_$u7b$$u7b$closure$u7d$$u7d$::h28a2ac9c5e0b3c24 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/thread/mod.rs:542:17 (san-data-race+0x9fc82) (BuildId: abaff10be3c90c7a985911bf9fb769fbad66acc6)
#3 _$LT$core..panic..unwind_safe..AssertUnwindSafe$LT$F$GT$$u20$as$u20$core..ops..function..FnOnce$LT$$LP$$RP$$GT$$GT$::call_once::hf30d54c2a60bd049 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/core/src/panic/unwind_safe.rs:272:9 (san-data-race+0x9ace2) (BuildId: abaff10be3c90c7a985911bf9fb769fbad66acc6)
#4 std::panicking::try::do_call::ha6f651f9e612b27e /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/panicking.rs:553:40 (san-data-race+0x95170) (BuildId: abaff10be3c90c7a985911bf9fb769fbad66acc6)
#5 __rust_try ea5e5nbwalr06882ygazitcju (san-data-race+0xa0358) (BuildId: abaff10be3c90c7a985911bf9fb769fbad66acc6)
#6 std::panicking::try::h2adff5b2e4f05561 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/panicking.rs:517:19 (san-data-race+0x9f0fe) (BuildId: abaff10be3c90c7a985911bf9fb769fbad66acc6)
#7 std::panic::catch_unwind::h2e6602efc4169fb7 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/panic.rs:350:14 (san-data-race+0x9f0fe)
#8 std::thread::Builder::spawn_unchecked_::_$u7b$$u7b$closure$u7d$$u7d$::h40871ab9f42880dc /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/thread/mod.rs:541:30 (san-data-race+0x9f0fe)
#9 core::ops::function::FnOnce::call_once$u7b$$u7b$vtable.shim$u7d$$u7d$::h2b08e2beafe17b93 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/core/src/ops/function.rs:250:5 (san-data-race+0x95971) (BuildId: abaff10be3c90c7a985911bf9fb769fbad66acc6)
#10 _$LT$alloc..boxed..Box$LT$F$C$A$GT$$u20$as$u20$core..ops..function..FnOnce$LT$Args$GT$$GT$::call_once::hbdeb5d489bfc9e66 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/alloc/src/boxed.rs:2064:9 (san-data-race+0xc253a) (BuildId: abaff10be3c90c7a985911bf9fb769fbad66acc6)
#11 _$LT$alloc..boxed..Box$LT$F$C$A$GT$$u20$as$u20$core..ops..function..FnOnce$LT$Args$GT$$GT$::call_once::hba97fe3013ab65e8 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/alloc/src/boxed.rs:2064:9 (san-data-race+0xc253a)
#12 std::sys::pal::unix::thread::Thread::new::thread_start::h01c5ff475a629e37 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/sys/pal/unix/thread.rs:108:17 (san-data-race+0xc253a)
Previous write of size 4 at 0x558040da1948 by main thread:
#0 san_data_race::main::ha84b3f5aaacb66cb /tmp/intro-to-rust/code/memory/src/bin/san-data-race.rs:34:14 (san-data-race+0x98e81) (BuildId: abaff10be3c90c7a985911bf9fb769fbad66acc6)
#1 core::ops::function::FnOnce::call_once::h758322e7ded22bf6 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/core/src/ops/function.rs:250:5 (san-data-race+0x95b3e) (BuildId: abaff10be3c90c7a985911bf9fb769fbad66acc6)
#2 std::sys::backtrace::__rust_begin_short_backtrace::h8c16abfc9d0ab508 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/sys/backtrace.rs:155:18 (san-data-race+0x98c91) (BuildId: abaff10be3c90c7a985911bf9fb769fbad66acc6)
#3 std::rt::lang_start::_$u7b$$u7b$closure$u7d$$u7d$::h153ec660acff75c1 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/rt.rs:159:18 (san-data-race+0x9c09e) (BuildId: abaff10be3c90c7a985911bf9fb769fbad66acc6)
#4 core::ops::function::impls::_$LT$impl$u20$core..ops..function..FnOnce$LT$A$GT$$u20$for$u20$$RF$F$GT$::call_once::h8ee6b536c2e4e076 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/core/src/ops/function.rs:284:13 (san-data-race+0xbaeac) (BuildId: abaff10be3c90c7a985911bf9fb769fbad66acc6)
#5 std::panicking::try::do_call::h5c8c98de8ed5bd5b /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/panicking.rs:553:40 (san-data-race+0xbaeac)
#6 std::panicking::try::h6315052de0e5fa0e /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/panicking.rs:517:19 (san-data-race+0xbaeac)
#7 std::panic::catch_unwind::h1530d3793f92a4bb /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/panic.rs:350:14 (san-data-race+0xbaeac)
#8 std::rt::lang_start_internal::_$u7b$$u7b$closure$u7d$$u7d$::he545ff4063dfc2c8 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/rt.rs:141:48 (san-data-race+0xbaeac)
#9 std::panicking::try::do_call::h09c77e8b42da26d9 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/panicking.rs:553:40 (san-data-race+0xbaeac)
#10 std::panicking::try::h7a9b2c58b7302b3b /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/panicking.rs:517:19 (san-data-race+0xbaeac)
#11 std::panic::catch_unwind::h464a2cd7183a7af5 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/panic.rs:350:14 (san-data-race+0xbaeac)
#12 std::rt::lang_start_internal::h99fdbebdafe8d634 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/rt.rs:141:20 (san-data-race+0xbaeac)
#13 main <null> (san-data-race+0x99049) (BuildId: abaff10be3c90c7a985911bf9fb769fbad66acc6)
Location is global 'san_data_race::SHARED_COUNTER::h58377d13dedd594a' of size 4 at 0x558040da1948 (san-data-race+0x123948)
Thread T2 (tid=174570, running) created by main thread at:
#0 pthread_create /rustc/llvm/src/llvm-project/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp:1023:3 (san-data-race+0x1497b) (BuildId: abaff10be3c90c7a985911bf9fb769fbad66acc6)
#1 std::sys::pal::unix::thread::Thread::new::h2a5a1c43e1035921 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/sys/pal/unix/thread.rs:87:19 (san-data-race+0xc2371) (BuildId: abaff10be3c90c7a985911bf9fb769fbad66acc6)
#2 std::thread::Builder::spawn_unchecked::hd5a840405c885ff3 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/thread/mod.rs:456:32 (san-data-race+0x9d025) (BuildId: abaff10be3c90c7a985911bf9fb769fbad66acc6)
#3 std::thread::Builder::spawn::ha557a18b7275cb76 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/thread/mod.rs:388:18 (san-data-race+0x9cd46) (BuildId: abaff10be3c90c7a985911bf9fb769fbad66acc6)
#4 std::thread::spawn::h0c5c2fd92f0917d0 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/thread/mod.rs:698:20 (san-data-race+0x9cd46)
#5 san_data_race::main::ha84b3f5aaacb66cb /tmp/intro-to-rust/code/memory/src/bin/san-data-race.rs:27:14 (san-data-race+0x98e73) (BuildId: abaff10be3c90c7a985911bf9fb769fbad66acc6)
#6 core::ops::function::FnOnce::call_once::h758322e7ded22bf6 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/core/src/ops/function.rs:250:5 (san-data-race+0x95b3e) (BuildId: abaff10be3c90c7a985911bf9fb769fbad66acc6)
#7 std::sys::backtrace::__rust_begin_short_backtrace::h8c16abfc9d0ab508 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/sys/backtrace.rs:155:18 (san-data-race+0x98c91) (BuildId: abaff10be3c90c7a985911bf9fb769fbad66acc6)
#8 std::rt::lang_start::_$u7b$$u7b$closure$u7d$$u7d$::h153ec660acff75c1 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/rt.rs:159:18 (san-data-race+0x9c09e) (BuildId: abaff10be3c90c7a985911bf9fb769fbad66acc6)
#9 core::ops::function::impls::_$LT$impl$u20$core..ops..function..FnOnce$LT$A$GT$$u20$for$u20$$RF$F$GT$::call_once::h8ee6b536c2e4e076 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/core/src/ops/function.rs:284:13 (san-data-race+0xbaeac) (BuildId: abaff10be3c90c7a985911bf9fb769fbad66acc6)
#10 std::panicking::try::do_call::h5c8c98de8ed5bd5b /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/panicking.rs:553:40 (san-data-race+0xbaeac)
#11 std::panicking::try::h6315052de0e5fa0e /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/panicking.rs:517:19 (san-data-race+0xbaeac)
#12 std::panic::catch_unwind::h1530d3793f92a4bb /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/panic.rs:350:14 (san-data-race+0xbaeac)
#13 std::rt::lang_start_internal::_$u7b$$u7b$closure$u7d$$u7d$::he545ff4063dfc2c8 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/rt.rs:141:48 (san-data-race+0xbaeac)
#14 std::panicking::try::do_call::h09c77e8b42da26d9 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/panicking.rs:553:40 (san-data-race+0xbaeac)
#15 std::panicking::try::h7a9b2c58b7302b3b /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/panicking.rs:517:19 (san-data-race+0xbaeac)
#16 std::panic::catch_unwind::h464a2cd7183a7af5 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/panic.rs:350:14 (san-data-race+0xbaeac)
#17 std::rt::lang_start_internal::h99fdbebdafe8d634 /rustc/20ae37c18df95f9246c019b04957d23b4164bf7a/library/std/src/rt.rs:141:20 (san-data-race+0xbaeac)
#18 main <null> (san-data-race+0x99049) (BuildId: abaff10be3c90c7a985911bf9fb769fbad66acc6)
SUMMARY: ThreadSanitizer: data race /tmp/intro-to-rust/code/memory/src/bin/san-data-race.rs:30:13 in san_data_race::main::_$u7b$$u7b$closure$u7d$$u7d$::hca1d1aa2bd214a46
==================
ThreadSanitizer: reported 1 warnings
通过报告我们能发现, ThreadSanitizer 确实发现了 data race 问题:
Write of size 4 at 0x558040da1948 by thread T2
#0 san_data_race::main:: /tmp/san-data-race.rs:30:13 (san-data-race+0x98906)
Previous write of size 4 at 0x558040da1948 by main thread:
#0 san_data_race::main:: /tmp//san-data-race.rs:34:14 (san-data-race+0x98e81)