diff options
| author | Lukas Markeffsky <@> | 2024-10-27 17:48:15 +0100 |
|---|---|---|
| committer | Lukas Markeffsky <@> | 2024-10-27 18:32:36 +0100 |
| commit | 4a71a592819b6fe87377dd5f857218ed37dbf195 (patch) | |
| tree | 5cd074988d5f7bfcf686cc169ff832cfc4c6ae27 /library/alloc/src/sync.rs | |
| parent | 8a9f40043fb6177a8a6d720103bac4e8889e0732 (diff) | |
| download | rust-4a71a592819b6fe87377dd5f857218ed37dbf195.tar.gz rust-4a71a592819b6fe87377dd5f857218ed37dbf195.zip | |
Rc/Arc: don't leak the allocation if drop panics
Diffstat (limited to 'library/alloc/src/sync.rs')
| -rw-r--r-- | library/alloc/src/sync.rs | 16 |
1 files changed, 9 insertions, 7 deletions
diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 15a1b0f2834..98a2fe24257 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -1872,15 +1872,17 @@ impl<T: ?Sized, A: Allocator> Arc<T, A> { // Non-inlined part of `drop`. #[inline(never)] unsafe fn drop_slow(&mut self) { + // Drop the weak ref collectively held by all strong references when this + // variable goes out of scope. This ensures that the memory is deallocated + // even if the destructor of `T` panics. + // Take a reference to `self.alloc` instead of cloning because 1. it'll last long + // enough, and 2. you should be able to drop `Arc`s with unclonable allocators + let _weak = Weak { ptr: self.ptr, alloc: &self.alloc }; + // Destroy the data at this time, even though we must not free the box // allocation itself (there might still be weak pointers lying around). - unsafe { ptr::drop_in_place(Self::get_mut_unchecked(self)) }; - - // Drop the weak ref collectively held by all strong references - // Take a reference to `self.alloc` instead of cloning because 1. it'll - // last long enough, and 2. you should be able to drop `Arc`s with - // unclonable allocators - drop(Weak { ptr: self.ptr, alloc: &self.alloc }); + // We cannot use `get_mut_unchecked` here, because `self.alloc` is borrowed. + unsafe { ptr::drop_in_place(&mut (*self.ptr.as_ptr()).data) }; } /// Returns `true` if the two `Arc`s point to the same allocation in a vein similar to |
