@@ -993,11 +993,14 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
993
993
bytes
994
994
}
995
995
996
- /// Find leaked allocations. Allocations reachable from `static_roots` or a `Global` allocation
997
- /// are not considered leaked, as well as leaks whose kind's `may_leak()` returns true.
998
- pub fn find_leaked_allocations (
999
- & self ,
1000
- static_roots : & [ AllocId ] ,
996
+ /// Find leaked allocations, remove them from memory and return them. Allocations reachable from
997
+ /// `static_roots` or a `Global` allocation are not considered leaked, as well as leaks whose
998
+ /// kind's `may_leak()` returns true.
999
+ ///
1000
+ /// This is highly destructive, no more execution can happen after this!
1001
+ pub fn take_leaked_allocations (
1002
+ & mut self ,
1003
+ static_roots : impl FnOnce ( & Self ) -> & [ AllocId ] ,
1001
1004
) -> Vec < ( AllocId , MemoryKind < M :: MemoryKind > , Allocation < M :: Provenance , M :: AllocExtra , M :: Bytes > ) >
1002
1005
{
1003
1006
// Collect the set of allocations that are *reachable* from `Global` allocations.
@@ -1008,7 +1011,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
1008
1011
self . memory . alloc_map . filter_map_collect ( move |& id, & ( kind, _) | {
1009
1012
if Some ( kind) == global_kind { Some ( id) } else { None }
1010
1013
} ) ;
1011
- todo. extend ( static_roots) ;
1014
+ todo. extend ( static_roots ( self ) ) ;
1012
1015
while let Some ( id) = todo. pop ( ) {
1013
1016
if reachable. insert ( id) {
1014
1017
// This is a new allocation, add the allocation it points to `todo`.
@@ -1023,13 +1026,15 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
1023
1026
} ;
1024
1027
1025
1028
// All allocations that are *not* `reachable` and *not* `may_leak` are considered leaking.
1026
- self . memory . alloc_map . filter_map_collect ( |id, ( kind, alloc) | {
1027
- if kind. may_leak ( ) || reachable. contains ( id) {
1028
- None
1029
- } else {
1030
- Some ( ( * id, * kind, alloc. clone ( ) ) )
1031
- }
1032
- } )
1029
+ let leaked: Vec < _ > = self . memory . alloc_map . filter_map_collect ( |& id, & ( kind, _) | {
1030
+ if kind. may_leak ( ) || reachable. contains ( & id) { None } else { Some ( id) }
1031
+ } ) ;
1032
+ let mut result = Vec :: new ( ) ;
1033
+ for & id in leaked. iter ( ) {
1034
+ let ( kind, alloc) = self . memory . alloc_map . remove ( & id) . unwrap ( ) ;
1035
+ result. push ( ( id, kind, alloc) ) ;
1036
+ }
1037
+ result
1033
1038
}
1034
1039
1035
1040
/// Runs the closure in "validation" mode, which means the machine's memory read hooks will be
0 commit comments