I'm learning Rust and I was playing with Box
, so I tried checking leaks with valgrind
but it shows that there are no allocations on the heap:
$ rustc -C opt-level=0 raii.rs
$ valgrind ./raii
==3850== Memcheck, a memory error detector
==3850== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==3850== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==3850== Command: ./raii
==3850==
5
Changed:10
==3850==
==3850== HEAP SUMMARY:
==3850== in use at exit: 0 bytes in 0 blocks
==3850== total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==3850==
==3850== All heap blocks were freed -- no leaks are possible
==3850==
==3850== For counts of detected and suppressed errors, rerun with: -v
==3850== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
valgrind --leak-check=full ./raii
shows exaclty the same result.
Here's the Rust code:
fn main() {
let mut _box2 = Box::new(5i32);
println!("{}", _box2);
*_box2 = 10i32;
println!("Changed:{}", _box2);
{
let _box3 = Box::new(4i32);
}
}
Some other info:
$ rustc -V
rustc 1.8.0 (db2939409 2016-04-11)
$ valgrind --version
valgrind-3.10.1
$ uname -a
Linux 3.19.0-59-generic #65~14.04.1-Ubuntu SMP Tue Apr 19 18:57:09 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
Why is that? I thought Box
allocates the variable on the heap. Also, this example shows almost the same code and Valgrind shows allocations there.
If I add the following code:
let _stack = (1u64, 2u64, 3u64);
let _heap = Box::new((4u64, 5u64, 6u64));
println!("Memory used by stack: {} bytes", std::mem::size_of_val(&_stack));
println!("Memory used by heap: {} bytes", std::mem::size_of_val(&_heap));
It prints exactly what I expected:
$ ./raii
Memory used by stack: 24 bytes
Memory used by heap: 8 bytes
- In the second case, the tuple was placed on the heap and a pointer (8 bytes) was pushed to the stack.
- In the first case tuple was placed on the stack, so it takes 24 bytes.
Valgrind seems to be able to count heap allocations from other programs:
$ valgrind echo "test"
==4575== Memcheck, a memory error detector
==4575== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==4575== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==4575== Command: echo test
==4575==
test
==4575==
==4575== HEAP SUMMARY:
==4575== in use at exit: 0 bytes in 0 blocks
==4575== total heap usage: 30 allocs, 30 frees, 3,681 bytes allocated
==4575==
==4575== All heap blocks were freed -- no leaks are possible
==4575==
==4575== For counts of detected and suppressed errors, rerun with: -v
==4575== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Rust 1.32
As of Rust 1.32, the default allocator for an executable is now the system allocator, so you don't need to set anything by default.
Previous versions
Rust uses jemalloc as the allocator when you build a binary. The way that jemalloc is currently compiled does not contain the Valgrind hooks needed.
If you need the ability to track allocations with Valgrind, you can switch to the the system allocator if you are using nightly Rust.
See also: