1
Fork 0

Miri leak_report: do not report leaks of allocations that are reachable from globals

This commit is contained in:
Ralf Jung 2020-04-04 12:03:06 +02:00
parent 6050e523ba
commit 2c9d857e90

View file

@ -650,7 +650,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
allocs_to_print: &mut VecDeque<AllocId>, allocs_to_print: &mut VecDeque<AllocId>,
alloc: &Allocation<Tag, Extra>, alloc: &Allocation<Tag, Extra>,
) { ) {
for &(_, (_, target_id)) in alloc.relocations().iter() { for &(_, target_id) in alloc.relocations().values() {
if allocs_seen.insert(target_id) { if allocs_seen.insert(target_id) {
allocs_to_print.push_back(target_id); allocs_to_print.push_back(target_id);
} }
@ -713,12 +713,31 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
} }
pub fn leak_report(&self) -> usize { pub fn leak_report(&self) -> usize {
let leaks: Vec<_> = self // Collect the set of allocations that are *reachable* from `Global` allocations.
.alloc_map let reachable = {
.filter_map_collect(|&id, &(kind, _)| if kind.may_leak() { None } else { Some(id) }); let mut reachable = FxHashSet::default();
let global_kind = M::GLOBAL_KIND.map(MemoryKind::Machine);
let mut todo: Vec<_> = self.alloc_map.filter_map_collect(move |&id, &(kind, _)| {
if Some(kind) == global_kind { Some(id) } else { None }
});
while let Some(id) = todo.pop() {
if reachable.insert(id) {
if let Some((_, alloc)) = self.alloc_map.get(id) {
// This is a new allocation, add its relocations to `todo`.
todo.extend(alloc.relocations().values().map(|&(_, target_id)| target_id));
}
}
}
reachable
};
// All allocations that are *not* `reachable` and *not* `may_leak` are considered leaking.
let leaks: Vec<_> = self.alloc_map.filter_map_collect(|&id, &(kind, _)| {
if kind.may_leak() || reachable.contains(&id) { None } else { Some(id) }
});
let n = leaks.len(); let n = leaks.len();
if n > 0 { if n > 0 {
eprintln!("### LEAK REPORT ###"); eprintln!("The following memory was leaked:");
self.dump_allocs(leaks); self.dump_allocs(leaks);
} }
n n