Skip to content

Commit 0801512

Browse files
committed
allocator::win32::{CoTaskMem,IMalloc}: switch to alloc(...)?; free(...); instead size.max(1)
relates to #32
1 parent 486c084 commit 0801512

File tree

2 files changed

+21
-10
lines changed

2 files changed

+21
-10
lines changed

src/allocator/win32/cotaskmem.rs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use core::ptr::NonNull;
2020
/// | [`thin::Free::free`] | [`CoTaskMemFree`]
2121
///
2222
/// 1. `size` / `layout` of 0 bytes will allocate successfully
23-
/// 2. `new_size` / `new_layout` will be rounded up to at least 1 byte, otherwise [`CoTaskMemRealloc`] would free!
23+
/// 2. `new_size` / `new_layout.size()` of 0 bytes will go through alloc+free instead
2424
///
2525
/// ## References
2626
/// * [`IMalloc`](super::IMalloc) (stateful equivalent)
@@ -41,7 +41,7 @@ impl Meta for CoTaskMem {
4141

4242
/// - `CoTaskMemAlloc(0)` allocates successfully.
4343
/// - `CoTaskMemRealloc(ptr, 0)` **frees**.
44-
/// Note that [`thin::Realloc`] and [`fat::Realloc`] resolve this by always requesting at least 1 byte.
44+
/// Note that [`thin::Realloc`] and [`fat::Realloc`] resolve this by going through alloc + free for 0 bytes.
4545
///
4646
const ZST_SUPPORTED : bool = true;
4747
}
@@ -97,9 +97,15 @@ unsafe impl thin::Realloc for CoTaskMem {
9797
const CAN_REALLOC_ZEROED : bool = false;
9898

9999
unsafe fn realloc_uninit(&self, ptr: AllocNN, new_size: usize) -> Result<AllocNN, Self::Error> {
100-
// SAFETY: ✔️ `ptr` belongs to `self` per [`thin::Realloc::realloc_uninit`]'s documented safety preconditions, and thus was allocated with CoTaskMem{Alloc,Realloc}
101-
let alloc = unsafe { CoTaskMemRealloc(ptr.as_ptr().cast(), new_size.max(1)) };
102-
NonNull::new(alloc.cast()).ok_or(())
100+
if new_size == 0 {
101+
let alloc = thin::Alloc::alloc_uninit(self, new_size)?;
102+
unsafe { thin::Free::free(self, ptr) };
103+
Ok(alloc)
104+
} else {
105+
// SAFETY: ✔️ `ptr` belongs to `self` per [`thin::Realloc::realloc_uninit`]'s documented safety preconditions, and thus was allocated with CoTaskMem{Alloc,Realloc}
106+
let alloc = unsafe { CoTaskMemRealloc(ptr.as_ptr().cast(), new_size) };
107+
NonNull::new(alloc.cast()).ok_or(())
108+
}
103109
}
104110

105111
unsafe fn realloc_zeroed(&self, _ptr: AllocNN, _new_size: usize) -> Result<AllocNN, Self::Error> {

src/allocator/win32/imalloc.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use core::ptr::{NonNull, null_mut};
2323
/// | [`thin::SizeOf::size_of`] | [`IMalloc::GetSize`] <sup>\[3\]</sup>
2424
///
2525
/// 1. `size` / `layout` of 0 bytes will allocate successfully
26-
/// 2. `new_size` / `new_layout` will be rounded up to at least 1 byte, otherwise [`IMalloc::Realloc`] would free!
26+
/// 2. `new_size` / `new_layout.size()` of 0 bytes will go through alloc+free instead
2727
/// 3. size will be inconsistent for "zero" sized allocations
2828
///
2929
/// ## References
@@ -77,8 +77,7 @@ impl Meta for IMalloc {
7777

7878
/// - `IMalloc::Alloc(0)` allocates successfully.
7979
/// - `IMalloc::Realloc(ptr, 0)` **frees**.
80-
/// Note that [`thin::Realloc`] and [`fat::Realloc`] resolve this by always requesting at least 1 byte.
81-
/// - `IMalloc::GetSize(ptr)` will return inconsistent results for ZSTs as a result.
80+
/// Note that [`thin::Realloc`] and [`fat::Realloc`] resolve this by going through alloc + free for 0 bytes.
8281
///
8382
const ZST_SUPPORTED : bool = true;
8483
}
@@ -130,8 +129,14 @@ unsafe impl thin::Realloc for IMalloc {
130129
const CAN_REALLOC_ZEROED : bool = false;
131130

132131
unsafe fn realloc_uninit(&self, ptr: AllocNN, new_size: usize) -> Result<AllocNN, Self::Error> {
133-
let alloc = unsafe { self.0.Realloc(ptr.as_ptr().cast(), new_size.max(1)) };
134-
NonNull::new(alloc.cast()).ok_or(())
132+
if new_size == 0 {
133+
let alloc = thin::Alloc::alloc_uninit(self, new_size)?;
134+
unsafe { thin::Free::free(self, ptr) };
135+
Ok(alloc)
136+
} else {
137+
let alloc = unsafe { self.0.Realloc(ptr.as_ptr().cast(), new_size) };
138+
NonNull::new(alloc.cast()).ok_or(())
139+
}
135140
}
136141

137142
unsafe fn realloc_zeroed(&self, _ptr: AllocNN, _new_size: usize) -> Result<AllocNN, Self::Error> {

0 commit comments

Comments
 (0)