Rc/Arc: don't leak the allocation if drop panics · qinheping/verify-rust-std@28223bd (original) (raw)

2 files changed

lines changed

Original file line number Diff line number Diff line change
@@ -2256,17 +2256,14 @@ unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for Rc<T, A> {
2256 2256 unsafe {
2257 2257 self.inner().dec_strong();
2258 2258 if self.inner().strong() == 0 {
2259 -// destroy the contained object
2260 - ptr::drop_in_place(Self::get_mut_unchecked(self));
2261 -
2262 -// remove the implicit "strong weak" pointer now that we've
2263 -// destroyed the contents.
2264 -self.inner().dec_weak();
2265 -
2266 -if self.inner().weak() == 0 {
2267 -self.alloc
2268 -.deallocate(self.ptr.cast(), Layout::for_value_raw(self.ptr.as_ptr()));
2269 -}
2259 +// Reconstruct the "strong weak" pointer and drop it when this
2260 +// variable goes out of scope. This ensures that the memory is
2261 +// deallocated even if the destructor of `T` panics.
2262 +let _weak = Weak { ptr: self.ptr, alloc: &self.alloc };
2263 +
2264 +// Destroy the contained object.
2265 +// We cannot use `get_mut_unchecked` here, because `self.alloc` is borrowed.
2266 + ptr::drop_in_place(&mut (*self.ptr.as_ptr()).value);
2270 2267 }
2271 2268 }
2272 2269 }
Original file line number Diff line number Diff line change
@@ -1872,15 +1872,17 @@ impl<T: ?Sized, A: Allocator> Arc<T, A> {
1872 1872 // Non-inlined part of `drop`.
1873 1873 #[inline(never)]
1874 1874 unsafe fn drop_slow(&mut self) {
1875 +// Drop the weak ref collectively held by all strong references when this
1876 +// variable goes out of scope. This ensures that the memory is deallocated
1877 +// even if the destructor of `T` panics.
1878 +// Take a reference to `self.alloc` instead of cloning because 1. it'll last long
1879 +// enough, and 2. you should be able to drop `Arc`s with unclonable allocators
1880 +let _weak = Weak { ptr: self.ptr, alloc: &self.alloc };
1881 +
1875 1882 // Destroy the data at this time, even though we must not free the box
1876 1883 // allocation itself (there might still be weak pointers lying around).
1877 -unsafe { ptr::drop_in_place(Self::get_mut_unchecked(self)) };
1878 -
1879 -// Drop the weak ref collectively held by all strong references
1880 -// Take a reference to `self.alloc` instead of cloning because 1. it'll
1881 -// last long enough, and 2. you should be able to drop `Arc`s with
1882 -// unclonable allocators
1883 -drop(Weak { ptr: self.ptr, alloc: &self.alloc });
1884 +// We cannot use `get_mut_unchecked` here, because `self.alloc` is borrowed.
1885 +unsafe { ptr::drop_in_place(&mut (*self.ptr.as_ptr()).data) };
1884 1886 }
1885 1887
1886 1888 /// Returns `true` if the two `Arc`s point to the same allocation in a vein similar to