Open icmccorm opened 1 year ago
I think this is not so much a bug as poor API design. force_unlink
was originally designed to be used with UnsafeRef
where the lifetimes of objects are manually managed: you could fast_clear
a list and then re-use the existing objects in another list by force_unlink
ing them.
This was never designed to work with proper pointer types such as Box
or Rc
.
Gotcha! To clarify my thought process here:
I'm new to working with Rc
, so I had thought that you could get around this with a change to using Weak
, but from the docs:
Since a Weak reference does not count towards ownership, it will not prevent the value stored in the allocation from being dropped... Note however that a Weak reference does prevent the allocation itself (the backing store) from being deallocated.
And, sure enough, the same kind of leak will happen with a pretty minimal example:
use std::{rc::{Rc, Weak}};
fn main() {
let a = Rc::new(Box::new(1));
Weak::into_raw(Rc::downgrade(&a));
}
The pull request above eliminates the leak by switching away from Rc
to UnsafeRef
for the these test cases.
Miri found memory leaks in the following tests:
All assertions pass. Each test has a similar structure; here's a minimal example using
LinkedList
that recreates the issue:When executing this, Miri detects that
a
is leaked and provides the following output:I originally thought this was due to unwrapping the clone in instead of Rc, and passed
insert_before(...)
. To test this, I switched to using a modified ObjAdapter3 with WeakRc::downgrade(&a)
as a parameter toinsert_before
instead of making a clone. However, this did not correct the issue.Given the descriptions of both
force_unlink
andfast_clear
, I'm guessing that there are always going to be some precautions necessary to avoid memory leaks here. Could you confirm if this is a bug, and if not, what additional steps a user would need to take to avoid this type of leak when using these methods? Thanks!