diff --git a/crates/libs/strings/src/heap.rs b/crates/libs/strings/src/heap.rs new file mode 100644 index 0000000000..ffcb305bfd --- /dev/null +++ b/crates/libs/strings/src/heap.rs @@ -0,0 +1,40 @@ +use super::*; +use core::ffi::c_void; + +/// Allocate memory of size `bytes` using `HeapAlloc`. +pub fn heap_alloc(bytes: usize) -> crate::Result<*mut c_void> { + #[cfg(windows)] + let ptr: *mut c_void = unsafe { bindings::HeapAlloc(bindings::GetProcessHeap(), 0, bytes) }; + + #[cfg(not(windows))] + let ptr: *mut c_void = unsafe { + extern "C" { + fn malloc(bytes: usize) -> *mut c_void; + } + + malloc(bytes) + }; + + if ptr.is_null() { + Err(Error::from_hresult(HRESULT(bindings::E_OUTOFMEMORY))) + } else { + Ok(ptr) + } +} + +/// Free memory allocated by `heap_alloc`. +pub unsafe fn heap_free(ptr: *mut c_void) { + #[cfg(windows)] + { + bindings::HeapFree(bindings::GetProcessHeap(), 0, ptr); + } + + #[cfg(not(windows))] + { + extern "C" { + fn free(ptr: *mut c_void); + } + + free(ptr); + } +} diff --git a/crates/libs/strings/src/hstring.rs b/crates/libs/strings/src/hstring.rs index 53f8b9190a..8de3c265f2 100644 --- a/crates/libs/strings/src/hstring.rs +++ b/crates/libs/strings/src/hstring.rs @@ -104,7 +104,6 @@ impl Clone for HSTRING { } impl Drop for HSTRING { - #[inline] fn drop(&mut self) { if self.is_empty() { return; @@ -116,7 +115,7 @@ impl Drop for HSTRING { unsafe { let header = header.as_ref(); if header.flags & REFERENCE_FLAG == 0 && header.count.release() == 0 { - bindings::HeapFree(bindings::GetProcessHeap(), 0, header as *const _ as *mut _); + heap_free(header as *const _ as *mut _); } } } @@ -423,28 +422,23 @@ struct Header { } impl Header { - #[inline] fn alloc(len: u32) -> Result<*mut Header> { debug_assert!(len != 0); // Allocate enough space for header and two bytes per character. // The space for the terminating null character is already accounted for inside of `Header`. let alloc_size = core::mem::size_of::
() + 2 * len as usize; - unsafe { - let header = - bindings::HeapAlloc(bindings::GetProcessHeap(), 0, alloc_size) as *mut Header; - - if header.is_null() { - return Err(Error::from_hresult(HRESULT(bindings::E_OUTOFMEMORY))); - } + let header = heap_alloc(alloc_size)? as *mut Header; + unsafe { // Use `ptr::write` (since `header` is unintialized). `Header` is safe to be all zeros. header.write(core::mem::MaybeUninit::
::zeroed().assume_init()); (*header).len = len; (*header).count = RefCount::new(1); (*header).data = &mut (*header).buffer_start; - Ok(header) } + + Ok(header) } fn duplicate(&self) -> Result<*mut Header> { diff --git a/crates/libs/strings/src/lib.rs b/crates/libs/strings/src/lib.rs index 0f7bc8705e..9039e9b54f 100644 --- a/crates/libs/strings/src/lib.rs +++ b/crates/libs/strings/src/lib.rs @@ -29,6 +29,9 @@ use decode::*; mod ref_count; use ref_count::*; +mod heap; +use heap::*; + mod literals; pub use literals::*;