You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: src/allocator/c/aligned_malloc.rs
+41-14Lines changed: 41 additions & 14 deletions
Original file line number
Diff line number
Diff line change
@@ -78,10 +78,23 @@ impl Meta for AlignedMalloc {
78
78
79
79
constMAX_SIZE:usize = usize::MAX;
80
80
81
-
/// | Platform | Behavior |
82
-
/// | ------------------| ---------|
83
-
/// | Linux | Succeeds?
84
-
/// | Windows | Fails? [`_aligned_malloc`] explicitly documents "If \[...\] `size` is zero, this function invokes the invalid parameter handler, as described in [Parameter validation](https://learn.microsoft.com/en-us/cpp/c-runtime-library/parameter-validation). If execution is allowed to continue, this function returns `NULL` and sets `errno` to `EINVAL`."
81
+
/// ### Platform: OS X
82
+
/// Zero sized allocs succeed.
83
+
/// Reallocs are untested.
84
+
///
85
+
/// ### Platform: Linux
86
+
/// Zero sized allocs succeed.
87
+
/// Reallocs are untested.
88
+
///
89
+
/// ### Platform: Windows
90
+
///
91
+
/// [`_aligned_malloc`] is documented as failing when size = 0.
92
+
/// This is a lie: it succeeds, at least on 10.0.19045.5737.
93
+
/// OTOH, it may or may not trigger debug checks on other versions of windows or the CRT.
94
+
///
95
+
/// [`_aligned_realloc`], on the other hand, is documented as *freeing* when size = 0.
96
+
/// Tests seem to confirm it, resulting in heap corruption checks if the buffers are sufficiently used afterwards.
97
+
/// As such, `*::Realloc` will skip it in favor of [`_aligned_malloc`] and [`_aligned_free`] when size = 0.
85
98
///
86
99
#[doc = include_str!("_refs.md")]
87
100
constZST_SUPPORTED:bool = false;
@@ -174,21 +187,33 @@ unsafe impl fat::Free for AlignedMalloc {
Copy file name to clipboardExpand all lines: src/allocator/c/malloc.rs
+37-12Lines changed: 37 additions & 12 deletions
Original file line number
Diff line number
Diff line change
@@ -48,16 +48,24 @@ impl Meta for Malloc {
48
48
49
49
constMAX_SIZE:usize = usize::MAX;// *slightly* less in practice
50
50
51
-
/// "If the size of the space requested is zero, the behavior is implementation defined: either a null pointer is returned, or the behavior is as if the size were some nonzero value, except that the returned pointer shall not be used to access an object."
52
-
/// C89 § 7.20.3 ¶ 1
51
+
/// `malloc(0)` is implementation defined at best (C89 § 7.20.3 ¶ 1), but `realloc(ptr, 0)` is [straight up undefined behavior as of C23](https://en.cppreference.com/w/c/memory/realloc#:~:text=the%20behavior%20is%20undefined)?
52
+
/// This wrapper works around that problem by invoking `malloc(0)` then `free(ptr)`.
53
53
///
54
-
/// Null pointers will be translated into an [`Err`], so this is at least defined behavior, but consider using an [`adapt`](crate::allocator::adapt) allocator for ZST support.
54
+
/// Consider using an [`adapt`](crate::allocator::adapt) allocator for ZST support.
55
+
///
56
+
/// ### Platform: OS X
57
+
/// - `malloc(0)` *untested?*
58
+
/// - `realloc(ptr, 0)` *untested?*
59
+
///
60
+
/// ### Platform: Linux
61
+
/// - `malloc(0)` allocates
62
+
/// - `realloc(ptr, 0)` *untested?*
63
+
///
64
+
/// ### Platform: Windows
65
+
/// - `malloc(0)` allocates
66
+
/// - `_msize(zst)` returns `0`
67
+
/// - `realloc(ptr, 0)` **frees** - to avoid this causing problems, this wrapper replaces it with `malloc(0)`, `free(ptr)`.
55
68
///
56
-
/// | Platform | Behavior |
57
-
/// | ------------------| ----------|
58
-
/// | Linux | Allocate
59
-
/// | OS X | ???
60
-
/// | Windows | Allocate
61
69
constZST_SUPPORTED:bool = false;
62
70
}
63
71
@@ -130,12 +138,24 @@ unsafe impl thin::Realloc for Malloc {
// SAFETY: ✔️ `ptr` belongs to `self` per thin::Realloc's documented safety preconditions, and thus was allocated with one of `malloc`, `calloc`, `realloc, or `_recalloc` - all of which should be safe to `realloc`.
134
-
let alloc = unsafe{realloc(ptr.as_ptr().cast(), new_size)};
135
-
NonNull::new(alloc.cast()).ok_or(())
141
+
if new_size == 0{// see <Malloc as Meta>::ZST_SUPPORTED rant above
142
+
let alloc = thin::Alloc::alloc_uninit(self, new_size)?;
143
+
unsafe{ thin::Free::free(self, ptr)};
144
+
Ok(alloc)
145
+
}else{
146
+
// SAFETY: ✔️ `ptr` belongs to `self` per thin::Realloc's documented safety preconditions, and thus was allocated with one of `malloc`, `calloc`, `realloc, or `_recalloc` - all of which should be safe to `realloc`.
147
+
let alloc = unsafe{realloc(ptr.as_ptr().cast(), new_size)};
0 commit comments