Hi guys, I ran into a Possible Memory Leak
issue recently. The issue is about how a static variable frees its memory. The complete code I used is shown as below:
use lazy_static::lazy_static;
use std::collections::HashMap;
use std::sync::RwLock;
#[derive(Clone, Debug)]
struct Circle {
radius: i32,
}
impl Drop for Circle {
fn drop(&mut self) {
println!("dropping circle: {}", self.radius);
}
}
// define a static variable
lazy_static! {
static ref HASHMAP: RwLock<HashMap<String, Circle>> = RwLock::new(HashMap::new());
}
fn main() {
{
let mut m = HASHMAP.write().unwrap();
(*m).insert("c1".to_string(), Circle { radius: 10 });
}
{
// drop `c1`
let mut m = HASHMAP.write().unwrap();
let c1 = m.remove("c1").unwrap();
drop(c1);
}
let size = HASHMAP.read().unwrap().len();
println!("size: {}", size);
}
I compiled the code above and used Valgrind to perform memory check:
# compile
cargo build --release
# run memory check
valgrind --leak-check=full --show-leak-kinds=definite,possible --log-file="result" target/release/test_static_map
The complete Valgrind report is
==688705== Memcheck, a memory error detector
==688705== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==688705== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==688705== Command: target/release/test_static_map
==688705== Parent PID: 688558
==688705==
==688705==
==688705== HEAP SUMMARY:
==688705== in use at exit: 148 bytes in 1 blocks
==688705== total heap usage: 13 allocs, 12 frees, 3,331 bytes allocated
==688705==
==688705== 148 bytes in 1 blocks are possibly lost in loss record 1 of 1
==688705== at 0x4848899: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==688705== by 0x10E13E: _ZN9hashbrown3raw21RawTable$LT$T$C$A$GT$14reserve_rehash17h0b184eda0aaee77dE.llvm.9777120827388291557 (in /home/ubuntu/workspace/test_static_map/target/release/test_static_map)
==688705== by 0x112573: hashbrown::map::HashMap<K,V,S,A>::insert (in /home/ubuntu/workspace/test_static_map/target/release/test_static_map)
==688705== by 0x111E8A: test_static_map::main (in /home/ubuntu/workspace/test_static_map/target/release/test_static_map)
==688705== by 0x112432: std::sys_common::backtrace::__rust_begin_short_backtrace (in /home/ubuntu/workspace/test_static_map/target/release/test_static_map)
==688705== by 0x112448: _ZN3std2rt10lang_start28_$u7b$$u7b$closure$u7d$$u7d$17h70a0ed67c352bcbbE.llvm.8328676566673015485 (in /home/ubuntu/workspace/test_static_map/target/release/test_static_map)
==688705== by 0x129C1A: std::rt::lang_start_internal (function.rs:284)
==688705== by 0x112424: main (in /home/ubuntu/workspace/test_static_map/target/release/test_static_map)
==688705==
==688705== LEAK SUMMARY:
==688705== definitely lost: 0 bytes in 0 blocks
==688705== indirectly lost: 0 bytes in 0 blocks
==688705== possibly lost: 148 bytes in 1 blocks
==688705== still reachable: 0 bytes in 0 blocks
==688705== suppressed: 0 bytes in 0 blocks
==688705==
==688705== For lists of detected and suppressed errors, rerun with: -s
==688705== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
My question is about these two parts:
- "148 bytes in 1 blocks are possibly lost in loss record 1 of 1"
- "ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)"
After lots of experiments, for now, it seems the "possibly lost" could be caused by the static variable. I'm a newbie of Valgrind, so I am not sure if Valgrind could detect the memory free of a lazy_static variable. Do you have any idea about the "possibly lost"? Any comment is welcome. Thanks a lot!